7.微软亚院之编程判断俩个链表是否相交(如果需要求出俩个链表相交的第一个节点)

问题:

微软亚院之编程判断俩个链表是否相交
给出俩个单向链表的头指针,比如h1,h2,判断这俩个链表是否相交。
为了简化问题,我们假设俩个链表均不带环。
问题扩展:

2.如果需要求出俩个链表相交的第一个节点列?


答案:

参考文章:http://blog.csdn.net/lihappy999/article/details/7330175

//20121127
#include <iostream>
using namespace std;

typedef struct node   
{  
	int num;  
	node* next;  
}node;  
void generateList(const bool circleTrue,node *&head1,node *&head2);
//产生链表,两个链表相交,circleTrue 为true表示产生环,false为不带环
//产生的链表结构肯定是相同的
bool judgeCircle(node* const head);//判断是否存在环,true存在,false不存在 
node* crossNode(const bool circleTrue,node *head1,node *head2);
int main()
{
	node* head1;
	node* head2;
	generateList(true,head1,head2);//相交,且有环
	bool b=judgeCircle(head1);
	node* p=crossNode(b,head1,head2);
	cout<<"cross node:"<<p->num<<endl;
	return 0;
}
void generateList(const bool circleTrue,node *&head1,node *&head2)
{
	//每个链表都具有10个节点  
	node *pre1=NULL;  
	node *p=new node;  
	head1=p;  
	p->num=rand();  
	p->next=NULL;  
	pre1=p;  

	node *pre2=NULL;  
	p=new node;  
	head2=p;  
	p->num=rand();  
	p->next=NULL;  
	pre2=p;

	//假设从第3个节点开始相交  
	int crossID=3;  
	//假设环的开始节点为5
	int circleStart=5;
	node *cs1=NULL;
	node *cs2=NULL;


	for (int i=0;i<10;++i)  
	{  
		//第一条链表的节点  
		p=new node;  
		pre1->next=p;  
		p->num=rand();  
		p->next=NULL;  
		pre1=p;  
		if (i==circleStart)
		{
			cs1=p;
		}
		if (i==crossID)
		{
			cs2=p;
		}
	}
	if (circleTrue)
	{
		pre1->next=cs1;
	}

	for (int i=0;i<5;++i)
	{
		p=new node;  
		pre2->next=p;  
		p->num=rand();  
		p->next=NULL;  
		pre2=p;
	}
	pre2->next=cs2;
}

bool judgeCircle(node* const head)  
{  
	//两个指针,一个每次走一步,一个每次走两步,当前一个指针赶上后一个指针时,就说明存在环  
	node* p1=head;  
	node* p2=head;  
	while ((p1->next!=NULL)&&(p2->next!=NULL))  
	{  
		p1=p1->next;  
		p2=p2->next->next;  
		if (p1==p2)  
		{  
			break;  
		}  
	}  
	if (p2->next==NULL)  
	{  
		return false;  
	}  
	else  
	{  
		return true;  
	}  
}  
node* crossNode(const bool circleTrue,node *head1,node *head2)
{
	
	if (!circleTrue)
	{
		//不存在环
		int num1=1;
		int num2=1;
		node* p1=head1;
		node* p2=head2;
		while (head1->next!=NULL)
		{
			num1++;
			head1=head1->next;
		}
		while (head2->next!=NULL)
		{
			num2++;
			head2=head2->next;
		}
		int preNum=num1>=num2?num1-num2:num2-num1;//对齐处理
		if (num1>=num2)
		{
			for (int i=0;i<preNum;i++)
			{
				p1=p1->next;
			}
		}
		else
		{
			for (int i=0;i<preNum;i++)
			{
				p2=p2->next;
			}
		}
		while (p1!=p2)
		{
			p1=p1->next;
			p2=p2->next;
		}
		return p1;
	}
	else
	{
		//存在环
		//分两种情况,入环口相同和入环口不同
		node* p1=head1;
		node* p2=head1;
		p1=p1->next;
		p2=p2->next->next;
		while (p1!=p2)
		{
			p1=p1->next;
			p2=p2->next->next;
		}
		//相遇点p2
		p1=head1;
		node* entraNode;
		while (p1!=p2)
		{
			p1=p1->next;
			entraNode=p2;
			p2=p2->next;
		}
		//相遇点p1的前一点pre即为环的入口点
		
		p1=head1;
		p2=head2;
		int num1=0;
		while (p1->next!=entraNode)
		{
			num1++;
			p1=p1->next;
		}
		int num2=0;
		while (p2->next!=entraNode)
		{
			num2++;
			p2=p2->next;
		}
		p1=head1;
		p2=head2;
		int preNum=num1>=num2?num1-num2:num2-num1;//对齐处理
		if (num1>=num2)
		{
			for (int i=0;i<preNum;i++)
			{
				p1=p1->next;
			}
		}
		else
		{
			for (int i=0;i<preNum;i++)
			{
				p2=p2->next;
			}
		}
		while (p1!=p2)
		{
			p1=p1->next;
			p2=p2->next;
		}
		return p1;
	}
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值