兩個單鏈表是否相交(考慮有環和無環)

步驟如下:

(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;
}
帶環相交輸出結果:


兩個無環相交鏈表輸出結果:


發佈了62 篇原創文章 · 獲贊 23 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章