判斷倆個鏈表是否相交

判斷倆個鏈表是否相交node

給出倆個單向鏈表的頭指針,好比 h1,h2,判斷這倆個鏈表是否相交。spa

爲了簡化問題,咱們假設倆個鏈表均不帶環。指針

問題擴展:code

若是須要求出倆個鏈表相交的第一個節點列ast


鏈表定義class

typedef struct node
{
	int data;
	struct node * next;
}List;


若是不帶環,那麼分別遍歷兩個鏈表到尾節點。
擴展

若果兩個鏈表相交,那麼尾節點必定相交List

若是兩個鏈表不相交,那麼尾節點必定不相交;循環

int isJoinedNocylic(List * h1,List * h2)
{
	while(h1 != NULL)
		h1 = h1->next;
	while(h2 != NULL)
		h2 = h2->next;
	
	return h1 == h2;
}


若是須要求出倆個鏈表相交的第一個節點列?遍歷

網上看到了這樣的一個解法:設置兩個指針fast和slow,初始值都指向頭,slow每次前進一步,fast每次前進二步,若是鏈表存在環,則fast一定先進入環,而slow後進入環,兩個指針一定相遇。(固然,fast先行頭到尾部爲NULL,則爲無環鏈表),這樣就能夠判斷兩個鏈表是否相交了,程序以下:

int isCycle(List * h)
{
	List * p1, * p2;
	p1 = p2 = h;
	int flag;
	
	while(p2 != NULL && p2->next != NULL)
	{
		p1 = p1->next;
		p2 = p2->next->next;
		if(p1 == p2)
		{	
			flag = 1;
			break;
		}
	}
	
	flag = 0;	
	return flag;
}

下面看看怎麼找環的入口,當fast與slow相遇時,slow確定沒有走遍歷完鏈表,而fast已經在環內循環了n圈(1<=n)。假設slow走了s步,則fast走了2s步(fast步數還等於s 加上在環上多轉的n圈),設環長爲r,則:
2s = s + nr
s= nr
設整個鏈表長L,入口環與相遇點距離爲x,起點到環入口點的距離爲a。
a + x = nr
a + x = (n – 1)r +r = (n-1)r + L - a
a = (n-1)r + (L – a – x)
(L – a – x)爲相遇點到環入口點的距離,由此可知,從鏈表頭到環入口點等於(n-1)循環內環+相遇點到環入口點(從相遇點向後遍歷循環回到入口點的距離),因而咱們從鏈表頭、與相遇點分別設一個指針,每次各走一步,兩個指針一定相遇,且相遇點爲環入口點,也即爲兩個鏈表的第一個相同節點。程序描述以下:

List *  isJoined(List * h1,List * h2)
{
	List * ph1,*p1,*p2;
	int flag;
 
	ph1 = h1; 
	while(ph1->next != NULL)
		ph1 = ph1->next;	
	ph1->next = h2;

	if(0 == isCycle(h1))
	{
		flag = 0;
	}
	else
	{
		p1 = h1;
		while(p1 != p2)
		{
			p1 = p1->next;
			p2 = p2->next;
		}
		flag = p1;
	}
	
	return flag;
}
相關文章
相關標籤/搜索