《劍指offer》:[37]如何得到連結串列環的入口地址

塵虛緣_KY發表於2016-06-19
題目:如何得到連結串列環的入口結點
方案:分兩步走:
第一步:先要找到連結串列中的環,得到環的結點的個數。可以設定兩個指標一個走的比較快,一個比較慢,那麼如果連結串列中存在一個環,那麼這兩個指標一定會陷入這個環中,快的指標一定會遇到慢的指標,所以很快就能遇到。因為前面有詳細講過,這裡不再多介紹,給一張圖吧。
第二步:得到環的個數以後,我們照樣可以設定兩個指標。第一個指標先前進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 INVALID@!"<<endl;
	else
	{
		EnterNode=EntryNodeOfLoop(pHead,NodeCircle);
		cout<<"環入口結點的值為:"<<EnterNode->data<<endl;
	}
	system("pause");
	return 0;
}

執行結果如下:











相關文章