题目:如何得到链表环的入口结点
方案:分两步走:
第一步:先要找到链表中的环,得到环的结点的个数。可以设置两个指针一个走的比较快,一个比较慢,那么如果链表中存在一个环,那么这两个指针一定会陷入这个环中,快的指针一定会遇到慢的指针,所以很快就能遇到。因为前面有详细讲过,这里不再多介绍,给一张图吧。
第二步:得到环的个数以后,我们照样可以设置两个指针。第一个指针先前进N(N为环中结点的个数)步,然后和第二个指针以相同的速度前进,当它们相遇时的结点就是链表中环的入口。
具体过程如下图所示:
具体实现代码如下所示:
#include <iostream> using namespace std; struct List { int data; List *next; }; int arr[7]={1,2,3,4,5,6,7}; List *pHead=NULL; List *pNext=NULL; List *pEnd=NULL; bool InputInvalid=false; void Listhelp(List **head,int data) { List *temp=new List ; temp->data=data; temp->next=NULL; if(NULL==*head) { *head=temp; pEnd=temp; } else { pEnd->next=temp; pEnd=temp; } } void CreateList(List **head,int *array,int length) { for(int i=0;i<length;i++) Listhelp(head,array[i]); //制造一个环;7->4 List *temp=*head; while(temp->data!=4) temp=temp->next; pEnd->next=temp; } void show(List *head) { int count=0; while(head) { cout<<head->data<<" "; head=head->next; count++; if(count==15) break;//有环所以用break退出; } } int GetNumOfCircle(List *head) { int NodeCount=1; if(NULL==head) { InputInvalid=true; return 0; } List *pSlow=head->next; if(pSlow==NULL) { InputInvalid=true; return 0; } List *pFast=pSlow->next;// two steps; while(pSlow!=NULL && pFast!=NULL) { if(pFast==pSlow) break; //找到环; pSlow=pSlow->next; pFast=pFast->next; if(pFast!=NULL) pFast=pFast->next; } //计算环的个数; while(pFast->next!=pSlow) { pFast=pFast->next; NodeCount++; } return NodeCount; } //得到环的入口地址; List *EntryNodeOfLoop(List *head,int count) { List *pNode1=head; for(int i=0;i<count;i++) pNode1=pNode1->next; List *pNode2=head; while(pNode1!=pNode2) { pNode1=pNode1->next; pNode2=pNode2->next; } return pNode1; } int main() { int NodeCircle=0; List *EnterNode=NULL; CreateList(&pHead,arr,7); cout<<"有环4567:"; show(pHead); cout<<endl; NodeCircle=GetNumOfCircle(pHead); if(InputInvalid) cout<<"THE INPUT IS [email protected]!"<<endl; else { EnterNode=EntryNodeOfLoop(pHead,NodeCircle); cout<<"环入口结点的值为:"<<EnterNode->data<<endl; } system("pause"); return 0; }
运行结果如下:
时间: 2024-11-05 14:53:21