【单链表四道经典例题(必会)】

①逆置单链表
②链表的相交问题
③判断链表是否存在回文
④链表的环问题

第一道题: 逆置单链表

<1> 基本思想:我们将单链表的节点从前到后全部头插一次即可。
【单链表四道经典例题(必会)】_第1张图片
<2> 代码实现

#include
#include
#include
#include

typedef struct List
{
	int data;
	struct List* next;
}List,*PList;

void Init_List(PList L)
{
	assert(L != NULL);
	L->next = NULL;
}

void Insert_tail(PList L, int val)
{
	assert(L != NULL);
	struct List* pnewnode = (struct List*)malloc(sizeof(List) * 1);
	assert(pnewnode != NULL);
	pnewnode->data = val;

	struct List* p = L;
	for (p; p->next != NULL; p = p->next);

	pnewnode->next = p->next;
	p->next = pnewnode;
}

void Reverse(PList L)
{
	assert(L != NULL);
	struct List* p = L->next;
	L->next = NULL;

	struct List* q = p->next;
	while (p != q)
	{
		p->next = L->next;
		L->next = p;
		p = q;
		if (q->next != NULL)
		{
			q = q->next;
		}
	}
	p->next = L->next;
	L->next = p;
}

void Show(PList L)
{
	assert(L != NULL);
	struct List* p = L->next;
	for (p; p != NULL; p = p->next)
	{
		printf("%d ", p->data);
	}
	printf("\n\n");
}

int main()
{
	List head;
	Init_List(&head);
	printf("初始表:");
	Insert_tail(&head, 1);
	Insert_tail(&head, 3);
	Insert_tail(&head, 5);
	Insert_tail(&head, 7);
	Insert_tail(&head, 9);
	Show(&head);

	printf("逆置后:");
	Reverse(&head);
	Show(&head);
	return 0;
}

<3> 结果演示
【单链表四道经典例题(必会)】_第2张图片
第二道题 链表的相交问题
(1)判断两个链表是否相交?
(2)如果相交请找到相交的节点。

**<1>**基本思想:
(1)若两个链表相交则尾节点一定相等
【单链表四道经典例题(必会)】_第3张图片
(2)先比较两个链表的长度,定义两个指针变量,分别指向两个链表,让长的那个链表先走(长 - 短)长度的节点,然后两个指针一起向后走,当两个指针相遇时,则为相交的节点

<2> 代码实现

bool Intersect(PList L1, PList L2)
{
	struct List* p = L1;
	struct List* q = L2;

	for (p; p->next != NULL; p = p->next);
	for (q; q->next != NULL; q = q->next);

	if (p == q)
	{
		return true;
	}
	else
	{
		return false;
	}
}

int getsize(PList L)
{
	struct List* p = L->next;
	int length = 0;
	for (p; p != NULL; p = p->next)
	{
		length++;
	}
	return length;
}

struct List* getsect(PList L1, PList L2)
{
	int length1 = getsize(L1);
	int length2 = getsize(L2);

	struct List* p = length1 > length2 ? L1->next : L2->next;
	struct List* q = length1 > length2 ? L2->next : L1->next;

	for (int i = 0; i < abs(length1 - length2); i++)
	{
		p = p->next;
	}

	while(p != q)
	{
		p = p->next;
		q = q->next;
	}
	return p;
}

第三道题 判断链表是否存在回文

<1> 基本思想: 将单链表中的数据全部放到一个数组中,分别定义两个变量保存开始的下标和最后一个数据的下标,分别从前向后,从后向前,一一对比,若相等则分别走一次继续比较,(若不相等直接退出,即没有回文),直到两个变量相等或者交叉停止,返回真,即有回文。

<2> 代码实现

#include
#include
#include
#include

typedef struct List
{
	int data;
	struct List* next;
}List, * PList;

void Init_List(PList L)
{
	L->next = NULL;
}

void Insert_tail(PList L,int val)
{
	struct List* pnewnode = (struct List*)malloc(sizeof(List));
	pnewnode->data = val;
	struct List* p = L;
	for (p; p->next != NULL; p = p->next);
	pnewnode->next = p->next;
	p->next = pnewnode;
}

int getsize(PList L)
{
	struct List* p = L->next;
	int length = 0;
	for (p; p != NULL; p = p->next)
	{
		length++;
	}
	return length;
}

bool Identify(PList L)
{
	int length = getsize(L);
	int* ar = (int*)malloc(sizeof(int) * length);
	struct List* p = L->next;
	int i = 0;
	for (p; p!= NULL; p = p->next)
	{
		ar[i++] = p->data;
	}

	int left = 0;
	int right = length - 1;
	while (left < right)
	{
		if (ar[left] != ar[right])
		{
			return false;
		}
		else
		{
			left++;
			right--;
		}
	}
	return true;
}

int show(PList L)
{
	struct List* p = L->next;
	for (p; p != NULL; p = p->next)
	{
		printf("%d ", p->data);
	}
	printf("\n");
}

int main()
{
	List head;
	Init_List(&head);
	Insert_tail(&head, 1);
	Insert_tail(&head, 2);
	Insert_tail(&head, 3);
	Insert_tail(&head, 2);
	Insert_tail(&head, 1);

	show(&head);

	if (Identify(&head))
	{
		printf("存在回文\n");
	}
	else
	{
		printf("不存在回文\n");
	}
	return 0;
}

<3> 结果演示
【单链表四道经典例题(必会)】_第4张图片

第四道题 链表的环问题
(1)判断链表是否存在环
(2)若存在,找到入环节点

<1> 基本思想
(1)使用快慢指针来判断是否存在环,一个慢指针一次让他走一个节点,一个快指针一次让他走两个节点,若存在环则两指针会相等,只要快指针为NULL则不存在环

【单链表四道经典例题(必会)】_第5张图片
(2)【单链表四道经典例题(必会)】_第6张图片

<2> 代码实现

#include
#include
#include
#include
#include

typedef struct List
{
	int data;
	struct List* next;
}List, * PList;

void Init_List(PList L)
{
	L->next = NULL;
}

List* haveCirde(PList L)
{
	assert(L->next->next != NULL);
	struct List* slow = L->next;
	struct List* fast = L->next->next;

	while (fast != NULL && fast != slow)
	{
		slow = slow->next;
		if (fast->next == NULL)
		{
			return NULL;
		}
		else
		{
			fast = fast->next->next;
		}
	}
	if (fast == NULL)
	{
		return NULL;
	}
	else
	{
		printf("存在环");
	}

	struct List* p = L->next;
	struct List* q = fast;
	while (p != q)
	{
		p = p->next;
		q = q->next;
	}
	return q;
}

这四道题都是单链表中比较经典的题目,希望这篇博客能帮助大家更好的学习这些题目。
感谢阅读!

你可能感兴趣的:(数据结构,c语言)