①逆置单链表
②链表的相交问题
③判断链表是否存在回文
④链表的环问题
第一道题: 逆置单链表
<1> 基本思想:我们将单链表的节点从前到后全部头插一次即可。
<2> 代码实现:
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#include<assert.h>
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> 结果演示:
第二道题 链表的相交问题
(1)判断两个链表是否相交?
(2)如果相交请找到相交的节点。
**<1>**基本思想:
(1)若两个链表相交则尾节点一定相等
(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<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<stdbool.h>
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> 结果演示:
第四道题 链表的环问题
(1)判断链表是否存在环
(2)若存在,找到入环节点
<1> 基本思想:
(1)使用快慢指针来判断是否存在环,一个慢指针一次让他走一个节点,一个快指针一次让他走两个节点,若存在环则两指针会相等,只要快指针为NULL则不存在环。
(2)
<2> 代码实现:
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<stdbool.h>
#include<assert.h>
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;
}
这四道题都是单链表中比较经典的题目,希望这篇博客能帮助大家更好的学习这些题目。
感谢阅读!