如何判斷兩個單鏈表(無環)是否交叉

利用兩個鏈表交叉的性質,若兩個鏈表交叉,那麼從鏈表的交叉點到鏈表尾部,都是相同的節點。因此,鏈表的形狀是Y型的。因爲是單鏈表,我們無法從鏈表尾部開始向前遍歷,找到第一個相同的節點。因此,我們可以先遍歷單鏈表1,計算出其長度len1,再遍歷單鏈表2,計算出長度len2,判斷哪個鏈表是長鏈表,哪個鏈表是短鏈表,我們記長鏈表的頭節點爲cur1,長度爲len1,短鏈表的頭節點爲cur2,長度爲len2。長鏈表中,先從頭節點cur1往後走(len1 - len2)步,然後同時開始往後遍歷兩個鏈表,每當遍歷一個節點時,比較cur1和cur2是否相等,若相等則表示兩個鏈表是交叉的,若將兩個鏈表遍歷完之後,仍未找到相同的節點,那麼表面這兩個鏈表沒有交叉。

代碼如下:

#include <iostream>
#include <vector>
#include <map>
using namespace std;

struct listNode
{
	int val;
	struct listNode *next;
};

listNode *isIntersect(listNode *head1, listNode *head2)
{
	if (head1 == NULL || head2 == NULL)
	{
		return NULL;
	}
	listNode *cur1 = head1;
	listNode *cur2 = head2;
	// 求單鏈表1的長度len1
	int len1= 0, len2 = 0;
	while(cur1 != NULL)
	{
		++len1;
		cur1 = cur1->next;
	}
	cur1 = head1;
	// 求單鏈表2的長度len2
	while(cur2 !=  NULL)
	{
		++len2;
		cur2 = cur2->next;
	}
	cur2 = head2;
	// 長鏈表頭節點爲cur1,長度爲len1,短鏈表頭節點爲cur2,長度爲len2
	if (len1 < len2)
	{
		int tmp = len1;
		len1 = len2;
		len2 = tmp;
		listNode *temp = cur1;
		cur1 = cur2;
		cur2 = temp;
	}
	// 判斷兩鏈表是否交叉
	int diff = len1 - len2;
	while (diff--)
	{
		cur1 = cur1->next;
	}
	while(cur1 != NULL && cur2 != NULL)
	{
		if (cur1 == cur2)
		{
			return cur1;
		}
		cur1 = cur1->next;
		cur2 = cur2->next;
	}
	return NULL;
}

int main()
{
	// 先建立一個有11個節點的單鏈表:0-1-2-3-4-5-6-7-8-9-10
	listNode *head1 = new listNode;
	head1->val = 0;
	int n = 0;
	listNode *cur1 = head1;
	while(++n <= 10)
	{
		cur1->next = new listNode;
		cur1 = cur1->next;
		cur1->val = n;
	}
	cur1->next = NULL;
	cur1 = head1;
	n = 0;
	while(++n <= 5)
	{
		cur1 = cur1->next;
	}
	// 單鏈表2:  -1,-1,-2,-3,-4,-5,5,6,7,8,9,10
	listNode *head2 = new listNode;
	head2->val = -1;
	n = 0;
	listNode *cur2 = head2;
	while (++n <=5)
	{
		cur2->next = new listNode;
		cur2 = cur2->next;
		cur2->val = -n;
	}
	cur2->next = cur1;
	cur1 = head1;
	cur2 = head2;

	// 分別打印兩單鏈表的節點地址
	cout << "單鏈表1的節點地址爲:";
	while(cur1 != NULL)
	{
		cout << cur1 << " ";
		cur1 = cur1->next;
	}
	cout << endl;
	cout << "單鏈表2的節點地址爲:";
	while(cur2 != NULL)
	{
		cout << cur2 << " ";
		cur2 = cur2->next;
	}
	cout << endl;
	listNode *result = isIntersect(head1, head2);
	cout << "兩個鏈表的交叉節點地址爲" << result << endl;

	return 0;
}

程序運行結果如下:



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章