题目描述:输入两个链表,找出它们的第一个公共结点。这里的公共结点不是指数据域哦,而是指整个结点,所以可知,如果有第一个公共结点,则后面所有结点都一样,呈现的像是Y;
思路分析:三种方法
第一种方法:蛮力法:从链表1开始遍历,遇到一个结点,就遍历链表2的所有结点,找到相同的停止,不推荐,因为时间复杂度太大;
第二种方法:因为是Y形状,所以从后面找,一直找到不相同的结点的为止,因为没有前继指针,所以需要依靠栈来存储。
第三种方法:第一种方法的改进,找出两个链表的差值,让长的链表先走差值步,然后两个链表一起走,直到遇到合适的为止。
#include<iostream>
#include<stack>
using namespace std;
struct Node
{
int data;
Node *next;
};
Node* Insert_tail(Node *list,int value)//尾插
{
if(list == NULL)
{
return NULL;
}
Node *node = new Node;
node -> data = value;
node ->next = NULL;
Node *p = list;
for(;p->next !=NULL;p=p->next );
p->next = node;
return node;
}
/////////////第一种方法:蛮力法:从前面开始找,找到相同的停止,不推荐//////////////////
Node *GetMix_1(Node *h1,Node *h2)
{
h1 = h1->next;
Node *p = h2->next;
while(h1!=NULL)//遍历链表1
{
p = h2 ->next ;
while(p !=NULL)//遍历链表2
{
if(h1 == p)
{
return h1;
}
p = p -> next;
}
h1 = h1 ->next;
}
return NULL;
}
//////////////////////第二种方法:从后面找,一直找到不相同的/////////////////////////////////
Node *GetMix_2(Node *h1,Node *h2)
{
//因为想从后往前走,但是又没有前继指针,所以,就利用栈;
stack<Node *> s1; //栈1,存链表1
stack<Node *> s2; //栈2,存链表2;
h1 = h1->next ; //去掉头
h2 = h2->next ; //去掉头
while(h1 != NULL)//往栈1里放东西
{
s1.push(h1);
h1 = h1 -> next;
}
while(h2!=NULL)//往栈2里放东西
{
s2.push(h2);
h2 = h2->next;
}
Node *p = s1.top();
Node *q = s2.top();
Node *s = NULL;
while(q == p)
{
s = p;
s1.pop(); //更新栈
s2.pop();
p = s1.top();//一直取栈顶元素
q = s2.top();
}
return s;
}
////////////////第三种方法:第一种方法的改进,让长的链表先走,然后两个链表一起走///////////////////////////////
Node *Item(Node *big,Node *small,int distance);//分函数,长的先走,然后一起走
Node *GetMix_3(Node *h1,Node *h2)
{
Node *p = h1 -> next;
int num1 = 0; //记录链表1的长度
while(p != NULL)
{
num1++;
p = p->next ;
}
int num2 = 0; //记录链表2的长度
p = h2 -> next;
while(p != NULL)
{
num2++;
p = p->next ;
}
int max = num1 > num2 ? num1 : num2;//找出比较大的一个
int distance = 0; //链表1和链表2的差值
p = NULL;
if(max == num1) //链表1长
{
distance = num1 - num2;
p = Item(h1,h2,distance); //调用分函数
}
else//链表2长
{
distance = num2 - num1;
p = Item(h2,h1,distance); //调用分函数
}
return p;
}
Node *Item(Node *big,Node *small,int distance)
{
while(distance >= 0) //先让长的走distance步
{
big = big->next ;
distance --;
}
small = small->next ; //去掉短的的头
while(big!=NULL && small!=NULL)//两个一起走
{
if(big == small)//遇到一样的了
{
return big;
}
big = big->next;
small = small->next;
}
return NULL;
}
void CreateList(Node *head1,Node *head2,Node *head3)//创建有公共结点的链表1和链表2;
{
int arr[] = {1,2,3,4};
int brr[] = {5,6};
int mix[] = {7,8,9};
int lenarr = sizeof(arr)/sizeof(arr[0]);
int lenbrr = sizeof(brr)/sizeof(brr[0]);
int lenmix = sizeof(mix)/sizeof(mix[0]);
Node * h1;
Node * h2;
Node * h3;
for(int i=0;i<lenarr;++i)
{
h1 = Insert_tail(head1,arr[i]); //尾插,链表1为:1 2 3 4
}
for(int i=0;i<lenbrr;++i)
{
h2 = Insert_tail(head2,brr[i]); //尾插,链表2为:5 6
}
for(int i=0;i<lenmix;++i)
{
h3 = Insert_tail(head3,mix[i]); //尾插,链表3为:7 8 9
}
h1->next = head3->next;//给链表1续链表3,链表1更新为:1 2 3 4 7 8 9
h2->next = head3->next;//给链表2续链表3,链表2更新为:5 6 7 8 9
}
void Show(Node *list)//打印函数
{
if(list == NULL)
return;
Node *p = list ->next;
for(;p != NULL;p = p->next)
{
cout<<p->data<<" ";
}
cout<<endl;
}
void clear(Node **list1,Node **list2,Node *pos)//清除
{
Node *p1 = *list1;
Node *p2 = *list2;
for(;p1!=NULL;)
{
Node *q = p1->next;
if(q!=pos)
{
p1->next = q->next;
delete q;
}
else
{
break;
}
}
delete p1;
for(;p2!=NULL;)
{
Node *q = p2->next;
if(q!=pos)
{
p2->next = q->next;
delete q;
}
else
{
break;
}
}
delete p2;
for(;pos->next!=NULL; )
{
Node *q = pos->next;
pos->next = q->next;
delete q;
}
delete pos;
}
int main()
{
Node *head1 = new Node; //创建带头链表1
head1 ->next = NULL;
Node *head2 = new Node;//创建带头链表2
head2 ->next = NULL;
Node *head3 = new Node;//创建带头链表3
head3 ->next = NULL;
CreateList(head1,head2,head3); //创建有公共结点的链表1和链表2;
Node *p1 = GetMix_1(head1,head2);
if(p1)
cout<<p1->data <<endl;
Node *p2 = GetMix_2(head1,head2);
if(p2)
cout<<p2->data <<endl;
Node *p3 = GetMix_3(head1,head2);
if(p3)
cout<<p3->data <<endl;
clear(&head1,&head2,p3);
return 0;
}