如何在双向链表中找到一个循环?如何消除循环?
答案 0 :(得分:2)
看看前面对这个问题的答案和评论,我发现他们使用的方法与检测单链表中的循环相同。但是,对于双链表,有更好的解决方法。
这是我的方法-
检测循环
在一个双向链接列表中,在迭代时,我们维护一个节点-“ last”代表刚好在当前节点之前的最后访问节点。如果任何节点上都有循环,则对于该节点,“上一个”指针(指向前一个节点的指针)将与“最后一个”节点不同。
另一方面,如果没有循环,我们将到达终点。
删除循环
我们只需将“ last”的“ next”更新为不指向任何内容(在C ++中为NULL)。
这是我的C ++实现:
#include <iostream>
using namespace std;
struct node{
int val;
node *next=NULL,*prev=NULL;
node(int x):val(x){}
};
bool detectAndRemoveLoopInDLL(node* head){
node* last = NULL;
while(head){
if(last && last!=head->prev){
cout<<"Loop found at: "<<head->val<<endl;
last->next = NULL;
return true;
}
last = head;
head = head->next;
}
cout<<"No loop found"<<endl;
return false;
}
int main() {
node* head = new node(1);
head->next = new node(2);
head->next->next = new node(3); head->next->prev = head;
head->next->next->next = new node(4); head->next->next->prev = head->next;
head->next->next->next->next = new node(5); head->next->next->next->prev = head->next->next;
head->next->next->next->next->next = new node(6); head->next->next->next->next->prev = head->next->next->next;
head->next->next->next->next->next->next = new node(7); head->next->next->next->next->next->prev = head->next->next->next->next;
head->next->next->next->next->next->next->next = new node(8); head->next->next->next->next->next->next->prev = head->next->next->next->next->next;
//comment this for no loop
head->next->next->next->next->next->next->next->next = head->next->next;
head->next->next->next->next->next->next->next->prev = head->next->next->next->next->next->next;
detectAndRemoveLoopInDLL(head);
return 0;
}
答案 1 :(得分:0)
将其视为单个链接列表并执行以下操作。
int detectloop(struct node *list)
{
struct node *slow_p = list, *fast_p = list;
while(slow_p && fast_p &&
fast_p->next )
{
slow_p = slow_p->next;
fast_p = fast_p->next->next;
if (slow_p == fast_p)
{
printf("Found Loop");
return 1;
}
}
return 0;
}
在上面的代码中,我们使用两个指针,一个是慢速,另一个是快速,慢速移动一步,快速移动两个步骤。它们都遇到的时间我们可以说链接列表正在循环不
void removeLoop(struct node *loop_node, struct node *head)
{
struct node *ptr1;
struct node *ptr2;
/* Set a pointer to the beging of the Linked List and
move it one by one to find the first node which is
part of the Linked List */
ptr1 = head;
while(1)
{
/* Now start a pointer from loop_node and check if it ever
reaches ptr2 */
ptr2 = loop_node;
while(ptr2->next != loop_node && ptr2->next != ptr1)
{
ptr2 = ptr2->next;
}
/* If ptr2 reahced ptr1 then there is a loop. So break the
loop */
if(ptr2->next == ptr1)
break;
/* If ptr2 did't reach ptr1 then try the next node after ptr1 */
else
ptr1 = ptr1->next;
}
/* After the end of loop ptr2 is the last node of the loop. So
make next of ptr2 as NULL */
ptr2->next = NULL;
}
在检测到循环之后,我们可以使用一个循环并从头开始并将慢速指针移动到通常的速度,当两个指针都满足会合点时,循环开始,我们就可以打破它。 / p>