一:单链表——④判断两个单链表是否相交

题目:输入两个链表的头节点,判断这两个链表是否存在相交

链表的定义如下:

typedef int Elemtype;
typedef struct ListNode
{
   Elemtype data;//值域
   ListNode *m_pNext;//指针域
}ListNode,*PListNode;

看到这个题目后大多数的人的第一反应应该就是,判断这两个链表的任意一个节点的指针是否相同,如果有那么这两个链表相交,否则不想交,然后呢用二重for循环来一一查找。显然这是一种笨方法,时间效率极其低下,那么我们来分析如何能够优化该解决方案呢?

首先我们先来分析,两个链表相交能出现哪些情况呢?

第一种:

在第n个节点开始这两条链表的后续重叠。好像两个相爱的人,在相遇了之后,便永不分离。

第二种:

这种相交情况在现实中虽然存在,但是呢,在链表目前的状态下,是无法实现的,因为每一个m_pNext指针只能指向下一个节点,并不能同时指向两个节点,除非我们在单个链表中的节点数据结构定义两个指针,树形链表,这里不做讨论。

第三种:

两条链表只在第n个节点相交,这种情况同上。

所以呢针对第一种情况,我们该怎么优化呢?

首先我们要比较这两个链表中的某任意节点的地址是一样呢。那么我们应该怎么比较呢?不能通过上面提到的穷举发,那么我们就要有一定的法则,我们观察第一种情况的图片可以发现,较长的链表的和较短的链表的 从后到前 长度为短链表的长度的部分是一一对应的,我们通过逆向思维,可以发现,长链表longlen减去短链表shortlen为mylen,我们让长链表先走到第mylen个节点,此时在和较短链表进行比较,此时他们是一一对应的。

调试代码如下:

测试:①输入任意一个为空的链表②输入两个不相交的链表③输入两个相交的链表

#include<assert.h>
#include<iostream>
using namespace std;

typedef int Elemtype;

typedef struct ListNode
{
	Elemtype data;//值域
	ListNode *m_pNext;//指针域
}ListNode,*PListNode;

ListNode* BuyNode()
{
	ListNode* p = (ListNode*)malloc(sizeof(ListNode));
	if(NULL == p)
	{
		printf("buynode is error:\n");
		exit(1);
	}
	memset(p,0,sizeof(ListNode));
	return p;
}

void InitList(PListNode &p)
{
	p = BuyNode();
	p->m_pNext = NULL;
	p->data = 0;
}
int GetLength(PListNode &head)//问题出现:不能直接操作head节点
{
	int count = 0;
	PListNode s = head;
	while(s!=NULL)
	{
		count+=1;
		s=s->m_pNext;
	}
	return count;
}
void InsertList(PListNode &p,Elemtype x,int pos)
{
	if(pos<1 || pos>GetLength(p)+1)
	{
		printf("input pos is error:\n");
		exit(1);
	}
	PListNode s = p;//头节点s
	if(pos == 1)
	{
		p->data = x;
		p->m_pNext = NULL;
	}
	else
	{
		while(pos-2)
	    {
			s = s->m_pNext;
		    --pos;
	     }//s指向前驱
	     PListNode r =s->m_pNext;

	     PListNode q = BuyNode();
	     q->data = x;

	     s->m_pNext = q;
	     q->m_pNext = r;
	}
}


void Show_List(PListNode &head)
{
	PListNode s =head;
	while(s != NULL)
	{
		printf("%d ",s->data);
		s = s->m_pNext;
	}
	printf("\n");
}
PListNode FirstNode(PListNode &phead,PListNode &qhead)
{
	assert(phead != NULL && qhead != NULL);
	int len1 = GetLength(phead);
	int len2 = GetLength(qhead);

	PListNode plong = phead;
	PListNode pshort = qhead;
	int my_len = len1-len2;

	if(len2>len1)
	{
		plong = qhead;
		pshort = phead;
		my_len = len2-len1;//my_len鐩稿樊鐨勯暱搴?
	}

	for(int i= 0;i < my_len;i++)
	{
		plong = plong->m_pNext;
	}
	while(plong != NULL && pshort != NULL && plong != pshort)
	{
		plong = plong->m_pNext;
		pshort = pshort->m_pNext;
		
	}
	
	
	PListNode FirstNode = plong;

	return FirstNode;
}
void main()
{
	PListNode phead;//第一个链表
	InitList(phead);
	for(int i=1;i<8;++i)
	{
		InsertList(phead,i+10,i);
	}
	Show_List(phead);

   
	PListNode qhead;//第二个链表
	InitList(qhead);
	for(int i=1;i<5;++i)
	{
		InsertList(qhead,i+10,i);
	}
	Show_List(qhead);

/*
//使两个链表相交的操作
	PListNode r = qhead;
	while(r->m_pNext != NULL)
	{
		r = r->m_pNext;
	}
	PListNode s = phead;
	for(int i=1;i<3;++i)
	{
		s = s->m_pNext;
	}
	r->m_pNext = s;
	Show_List(qhead);
	
*/

	PListNode p = FirstNode(phead,qhead);
	if(p != NULL)
	{
		printf("%d \n",p->data);
	}
	else
		printf("没有相交:\n");


}

调试①:终止。

调试②:

调试③:

 

猜你喜欢

转载自blog.csdn.net/genzld/article/details/81252714