两个单链表是否相交(考虑有环和无环)

步骤如下:

(1)判断两个单链表中是否有环,如果都没有环,则进入(2);如果都有环,则进入(3);如果一个有环,一个没有环,则必然不会相交。

(2)两个链表没环,则判断两个链表中最后一个结点是否相等(不只是值相等,须地址一样);

(3)先用快慢指针计算出一个环的入口结点,在判断此结点是否在另外一个带环链表上。

注意: 两个带环链表如果相交,则在创建2个带环链表时,则2个共同尾结点指向的下一结点应该一样(包括地址)。


代码如下:

// DoubleListCross.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<iostream>


typedef int type;
using namespace std;


//单链表结点
typedef struct node
{
	type data;
	struct node *next;
}node,*pNode;

//创建两个无环交叉链表或非交叉链表  a1为L1链表中的数据,长度为n1,m指L1与L2共有结点的长度
void CreateLists(pNode &L1,pNode &L2,type *a1,type *a2,int n1,int n2,int m)
{
    L1=(pNode)malloc(sizeof(node));
	if(NULL==L1)
	{
	  exit(-1);
	}
	 L2=(pNode)malloc(sizeof(node));
	if(NULL==L2)
	{
	  exit(-1);
	}
	L1->next=NULL; //创建头结点
	L2->next=NULL;

	pNode temp1=L1;
	pNode temp2=L2;

	for(int i=0;i<n1-m;i++)
	{
	  pNode p1=(pNode)malloc(sizeof(node));
	  if(NULL==p1)
	  {
	   exit(-1);
	  }
	  p1->data=a1[i];
	  p1->next=NULL;
       
	  temp1->next=p1;
	  temp1=p1;
	}
	for(int i=0;i<n2-m;i++)
	{
	  pNode p2=(pNode)malloc(sizeof(node));
	  if(NULL==p2)
	  {
	   exit(-1);
	  }
	  p2->data=a2[i];
	  p2->next=NULL;
       
	  temp2->next=p2;
	  temp2=p2;
	}

	//创建公用结点
	for(int i=n2-m;i<n2;i++)
	{
	   pNode p3=(pNode)malloc(sizeof(node));
	  if(NULL==p3)
	  {
	   exit(-1);
	  }
	  p3->data=a2[i];
	  p3->next=NULL;
       
	  temp2->next=p3;
	  temp2=p3;

	  temp1->next=p3;
	  temp1=p3;
	}

}

//创建2个有环交叉链表  a1为L1链表中的数据,长度为n1,m指L1与L2共有结点的长度 m1为L1入环结点标号
void CreateCircleLists(pNode &L1,pNode &L2,type *a1,type *a2,int n1, int n2, int m, int m1,int m2)
{
	L1=(pNode)malloc(sizeof(node));
	if(NULL==L1)
	{
	  exit(-1);
	}
	 L2=(pNode)malloc(sizeof(node));
	if(NULL==L2)
	{
	  exit(-1);
	}
	L1->next=NULL; //创建头结点
	L2->next=NULL;

	pNode temp1=L1;
	pNode temp2=L2;

	for(int i=0;i<n1-m;i++)
	{
	  pNode p1=(pNode)malloc(sizeof(node));
	  if(NULL==p1)
	  {
	   exit(-1);
	  }
	  p1->data=a1[i];
	  p1->next=NULL;
       
	  temp1->next=p1;
	  temp1=p1;
	}
	for(int i=0;i<n2-m;i++)
	{
	  pNode p2=(pNode)malloc(sizeof(node));
	  if(NULL==p2)
	  {
	   exit(-1);
	  }
	  p2->data=a2[i];
	  p2->next=NULL;
       
	  temp2->next=p2;
	  temp2=p2;
	}

	//创建公用结点
	for(int i=n2-m;i<n2;i++)
	{
	   pNode p3=(pNode)malloc(sizeof(node));
	  if(NULL==p3)
	  {
	   exit(-1);
	  }
	  p3->data=a2[i];
	  p3->next=NULL;
       
	  temp2->next=p3;
	  temp2=p3;

	  temp1->next=p3;
	  temp1=p3;
	}
     
	//建立环
	pNode p11=L1->next;
	pNode p22=L2->next;
	
	for(int i=1;i<m1;i++)
	{
		p11=p11->next;
	}
	temp1->next=p11;


	for(int j=1;j<m2;j++)
	{
		p22=p22->next;
	}
	temp2->next=p22;

}

//打印一个无环链表
void PrintList(pNode L)
{
	pNode temp=L->next;
	
	while(NULL!=temp)
	{
		cout<<temp->data<<" ";
		temp=temp->next;
	}

	cout<<endl;
}

//计算一个无环链表长度
int Len(pNode L)
{
   pNode temp=L->next;
   int i=0;
   
   while(NULL!=temp)
   {
     i++;
	temp= temp->next;
   }
   return i;
}
//取一个无环链表中某一结点
pNode GetNode(pNode L,int m)
{
	int len=Len(L);
	if((m<1)||(m>len))
	{
	 cout<<"Over!"<<endl;
	 exit(-1);
	}
    
	pNode temp=L->next;
	for(int i=0;i<m;i++)
	{
		temp=temp->next;
	}

	return temp;
}
//判断一个单链表是否有环  如果有环,返回环的入口结点  如果没有环,返回NULL
pNode IsCircle(pNode L)
{
	pNode fast=L;
	pNode slow=L;
	
	while(fast &&fast->next)
	{
		fast=fast->next->next;
		slow=slow->next;
		
		if(fast==slow)
		{
		    fast=L;
			while(fast!=slow)
			{
				fast=fast->next;
				slow=slow->next;
			}
			return slow;
		}
	
	}
	  return NULL;
	
	
}

//计算一个带环链表的长度
int LenCircle(pNode L)
{
	pNode p=L->next;
	pNode p1=IsCircle(L);//环的入口结点
	pNode p2=p1->next;
	int i=0;
	int j=1;
	while(p!=p1)
	{
	  i++;
	  p=p->next;
	}

	while(p2!=p1)
	{
	  j++;
	  p2=p2->next;
	}
	
	return i+j;
}
//判断一个环的入口结点是否在另外一条带环链表上
bool IsCircleNode(pNode p,pNode L)
{
	pNode temp=L->next;
	int len=LenCircle(L);
	
	for(int i=0;i<len;i++)
	{
	   if(temp==p)
	   {
	    return true;
	   }
	   temp=temp->next;
	}
	return false;
}


//判断2个无环单链表是否相交 如果相交返回相交点,否则返回NULL
pNode ListCross(pNode L1,pNode L2,int n1, int n2)
{
	pNode temp1=L1->next;
	pNode temp2=L2->next;
	
	if(GetNode(L1,n1)==GetNode(L2,n2))//判断尾结点相同
	{
	   if(n1>=n2)
	   {
	      for(int i=0;i<n1-n2;i++)
		  {
			  temp1=temp1->next;
		  }
	   }
	   else
	   {
	       for(int i=0;i<n2-n1;i++)
		  {
			  temp2=temp2->next;
		  }
	   }
	     while(temp1!=temp2)
		  {
			  temp1=temp1->next;
			  temp2=temp2->next;
		  }
		  return temp1;
	}
	else
	{
	  return NULL;
	}

}

int _tmain(int argc, _TCHAR* argv[])
{
	type a1[5]={1,2,3,4,5};
	type a2[7]={6,7,8,9,3,4,5};
	pNode L1=NULL;
	pNode L2=NULL;
	//CreateLists(L1,L2,a1,a2,5,7,3); 创建两个无环交叉链表
	CreateCircleLists(L1,L2,a1,a2,5,7,3,3,5);//创建两个有环交叉链表
	
	pNode p1=IsCircle(L1);
	pNode p2=IsCircle(L2);
	if((NULL==p1)&&(NULL==p2))//两个表无环
	{
	    pNode temp=ListCross(L1,L2,5,7);
		if(NULL==temp)
		{
		 cout<<"两无环链表不相交!"<<endl;
		}
		else
		{
			cout<<"两无环链表相交结点为:"<<temp->data<<endl;
		}
	}
	else if((NULL!=p1)&&(NULL!=p2)) //两个表都有环
	{
	  if(IsCircleNode(p1,L2))
	  {
	    cout<<"两带环链表相交!"<<endl;
	  }
	  else
	  {
	     cout<<"两带环链表不相交!"<<endl;
	  }
	}
	else
	{
	    cout<<"一个带环链表与一个无环链表一定不相交!"<<endl;
	}
	
	return 0;
}
带环相交输出结果:


两个无环相交链表输出结果:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值