3.6 程式設計判斷兩個連結串列是否相交
阿新 • • 發佈:2019-01-23
(一)題目:輸入一個單項鍊表,找出該連結串列的倒數第k個節點。
解法:設立兩個指標,先讓第一個指標先往前走k步,然後第二個指標放到連結串列開頭。
然後兩個連結串列一起往後走,當第一個連結串列到達連結串列尾部的時候,後面那個連結串列所在的位置就剛好是連結串列的倒數第k個節點!
程式碼:
struct node { int data; node *pNext; }; node* funtion(node *head, int k) { assert(k >= 0); node *pOne, *pTwo; pOne = head; pTwo = head; for(; k >0 && pTwo != NULL; k--) { pTwo = pTwo->pNext; } if(k > 0) return NULL; while(pTwo != NULL) { pOne = pOne -> pNext; pTwo = pTwo -> pNext; } return pOne; }
(二)題目:給定兩個單項鍊表,給定這兩個單項鍊表的頭指標,程式設計判斷這兩個連結串列是否相交。
方法:因為兩個連結串列如果相交的話,那麼從相交節點開始,到最後,這兩個連結串列的後面的部分都是公共的部分!
所以,只需要分別從兩個連結串列開頭,遍歷到最後結尾處,看看兩個尾部是不是相同的一個節點!如果是的話,說明這兩個連結串列是相交的,如果不是的話,說明這兩個 連結串列是不相交的。
題目:上面說的這種方法是兩個連結串列都不帶環,但是如果連結串列帶了環呢!?
所以總的方法:
(1)先判斷兩個連結串列帶不帶環
(2)如果都不帶環,就判斷兩個連結串列的尾節點是否相等。
(3)如果都帶環,判斷一連結串列上兩個指標相遇的那個節點,在不在另外一條連結串列上。如果在的話,則兩個連結串列相交。如果不在的話,則不相交。
程式碼:
struct node { int data; node *pNext; }; bool isCircle(node *head, node *&circleNode, node *&lastNode) { node *fast = head -> pNext; node *slow = head; while(fast && slow && fast != slow) { if(fast -> pNext != NULL) fast = fast -> pNext; if(fast -> pNext == NULL) lastNode = fast; if(slow -> pNext == NULL) lastNode = slow; fast = fast -> pNext; slow = slow -> pNext; } if(fast == slow && fast && slow) { circleNode = fast; return true; } else return false; } bool detect(node *head1, node *head2) { node *circleNode1; node *circleNode2; node *lastNode1; node *lastNode2; bool isCircle1 = isCircle(head1, circleNode1, lastNode1); bool isCircle2 = isCircle(head2, circleNode2, lastNode2); if(isCircle1 != isCircle2) return false; //兩個鏈變一個有環,一個無環 else if(!isCircle1 && !isCircle2) return lastNode1 == lastNode2; //兩個連結串列都無環 else { //兩個連結串列都有環 node *temp = circleNode1 -> pNext; while(temp != circleNode1) { if(temp == circleNode2) return true; temp = temp -> pNext; } return false; } return false; }
(三)求兩個連結串列相交的第一個節點
方法,思路:先求出更長的那個連結串列的,然後在這個連結串列上面先走長度之差的步數,然後兩個指標在一起走,走到最後,既是同一個節點!
struct node {
int data;
node *pNext;
};
unsigned int ListLength(node *pHead) {
unsigned int nLength = 0;
node *pNode = pHead;
while(pNode != NULL) {
nLength++;
pNode = pNode -> pNext;
}
return nLength;
}
node* FindFirstCommonNode(node *pHead1, node *pHead2) {
unsigned int nLength1 = ListLength(pHead1);
unsigned int nLength2 = ListLength(pHead2);
int nLengthDiff = nLength1 - nLength2;
node *pListHeadLong = pHead1;
node *pListHeadShort = pHead2;
if(nLength1 < nLength2) {
nLengthDiff = nLength2 - nLength1;
pListHeadLong = pHead2;
pListHeadShort = pHead1;
}
for(int i = 0; i < nLengthDiff; ++i) pListHeadLong = pListHeadLong -> pNext;
while(pListHeadLong != NULL && pListHeadShort != NULL && pListHeadLong != pListHeadShort) {
pListHeadLong = pListHeadLong -> pNext;
pListHeadShort = pListHeadShort -> pNext;
}
node *pFirstCommonNode = NULL;
if(pListHeadLong == pListHeadShort) pFirstCommonNode = pListHeadLong;
return pFirstCommonNode;
}