如果链表中含有圆环,那么对链表的遍历会有什么影响呢?
- 毋庸置疑,影响是很大的。

单判断单链表的成环的方法有两种:
首先介绍一种常用方法:试想有一个圆形跑道,甲乙两人同时在跑道的起点,如果甲的速度是乙的两倍,那么当乙跑完半圈时,甲跑完一圈回到起点,乙跑完一圈回到起点时,甲跑完两圈也回到起点,这样的话,甲乙重新在起点相遇。于是乎我们可以定义两个指针p1、p2均指向链表的第一个节点,指针p1后移一次遍历一个节点,指针p2后移一次遍历两个节点,现将两指针同时前进,如果两指针相遇就说明该单链表成环。
另外一种方法就是在时间复杂度为O(n)的前提下判断链表是否有环。首先我们为每一个链表设置一个标识flag = 0,用指针p来遍历该单链表,每遍历一个节点将标识flag重新置为1,当遍历到标识为1的节点时表示该单链表成环且该节点为环的起始节点,

计算环的长度:
- 当两指针相遇时,保持指针p1不变,移动指针p2一次遍历一个节点,用计数器记录移动次数,当两指针再次相遇时即可得出环的长度。
寻找环的起点位置:
- 入环起始点在头结点K跳的位置,环的长度为N也就是N跳;K可以写成:K=aN+b其中a=K/N;b=K%N;p1和p2相交时是处于环中从起始点开始第N-b的位置,也就是还需要b跳到入环起始结点;现在p3和p1同时起步,一起走,p1第一次和p3相遇的地方即为入环起始点;

代码实现:
//节点形式:
/*
typedef struct Node
{
int data;
struct Node *next;
}Node;
*/
//两指针法:
bool Is_RingLink1(Node *phead)
{
Node *p1 = phead;
Node *p2 = phead;
while(p1 != NULL && p2 != NULL)
{
p1 = p1->next;
p2 = p2->next->next;
if(p1 == p2)
{
return true;
}
}
return false;
}
//标识法
//节点形式:
/*
typedef struct Node
{
int data;
struct Node *next;
int flag = 0;
}Node;
*/
bool IS_RingLink2(Node *phead)
{
Node *p = phead;
while(p != NULL && p->flag != 1)
{
p->flag = 1;
p = p->next;

本文详细介绍了链表的各种操作,包括判断链表是否成环及如何找到环的起始位置和长度,解决链表相交问题并找到第一个相交节点,实现链表的逆置和从尾到头打印链表等。
最低0.47元/天 解锁文章
644

被折叠的 条评论
为什么被折叠?



