线性时间查找两个单链表的交叉结点
思路
为了解决本道题有多种解法。
方法 1)先将两个单链表LA和LB分别遍历一遍,获得各自的长度为m和n,假设m比n大,那么先对LA表从头遍历m-n个元素。接下来两个表同时遍历,若两个指针指向同一个结点,则停止。返回指向该结点的任一指针。
方法 2)先将两个单链表LA和LB分别遍历一遍,分别将各自的指针保存在两个栈中。然后同时对两个栈进行top操作,直到两个栈顶元素相等,也就是两个栈顶指针所指向的结点相同,则停止。返回指向该结点的任一指针。
本文实现的是方法1)。见以下代码中的getInterNode函数。merge函数是一个辅助函数,为了构造两个尾部结点相同的单链表。
代码
#include <iostream>
#include <vector>
#include <cassert>
#include <stack>
#include <string>
using namespace std;
typedef int Type;
struct Node
{
Type data;
Node * next;
};
void createList(Node * & phead, const vector<Type> & inp)
{
phead = new Node;
phead->data = inp.at(0);
phead->next = NULL;
Node * p = phead;
int i = 1;
while( i<inp.size() )
{
Node * pnew = new Node;
pnew->data = inp.at(i);
pnew->next = NULL;
p->next = pnew;
p = pnew;
i++;
}
}
void destroyList(Node * & phead)
{
assert(phead != NULL);
Node * pnext = phead->next;
while(pnext)
{
delete phead;
phead = pnext;
pnext = phead->next;
}
delete phead;
}
void mergeNode(Node *hA, Node *hB)
{
Node * headA = hA;
Node * headB = hB;
stack<Node *> chain1, chain2;
while( headA != NULL )
{
chain1.push( headA );
headA = headA -> next;
}
while( headB != NULL )
{
chain2.push( headB );
headB = headB -> next;
}
int lena=chain1.size(), lenb=chain2.size();
int len = 0;
Node * record = NULL;
assert ( chain1.top()->data == chain2.top()->data );
while( !chain1.empty() && !chain2.empty() && chain1.top()->data == chain2.top()->data )
{
chain1.pop();
chain2.pop();
lena--;
lenb--;
}
headA = hA;
headB = hB;
int rcA = 0, rcB = 0;
while( headA && rcA < lena )
{
rcA++;
headA = headA->next;
}
while( headB && rcB < lenb-1 )
{
rcB++;
headB = headB->next;
}
destroyList( headB->next );
headB->next = headA;
}
Node * getInterNode(Node *headA, Node *headB)
{
int rcA = 0, rcB = 0;
Node * ha = headA;
Node * hb = headB;
while( ha )
{
rcA++;
ha = ha->next;
}
while( hb )
{
rcB++;
hb = hb->next;
}
int sub = rcA>rcB ? (rcA-rcB) : (rcB-rcA);
ha = headA;
hb = headB;
int rc = 0;
while( rcA>rcB && ha && rc<sub )
{
rc++;
ha = ha->next;
}
while( rcA<rcB && hb && rc<sub )
{
rc++;
hb = hb->next;
}
while( ha && hb && ha != hb )
{
ha = ha->next;
hb = hb->next;
}
if (ha)
{
return ha;
}
else
{
return NULL;
}
}
int main()
{
int arr1[] = {0, 1, 2, 3, 4, 5};
int arr2[] = {7, 2, 3, 4, 5};
vector<Type> inp1(arr1, arr1+6);
vector<Type> inp2(arr2, arr2+5);
Node * l1 = NULL;
Node * l2 = NULL;
createList(l1, inp1);
createList(l2, inp2);
mergeNode(l1, l2);
Node * ret = getInterNode(l1, l2);
cout<<"cross node: "<<ret->data<<endl;
destroyList(l1);
destroyList(l2);
return 0;
}