判断两个无头结点的单链表是否相交

今天来说一下判断两个无头结点的单链表是否相交的代码,

无头结点的单链表自身分为两种情况,带环和不带环,

l1,l2分别代表两条链表,

用真值表来表示,1表示带环,0表示不带环

l1l2
00
01
10
11

首先我们来讨论一下较为简单的不带环的情况:


如图所示,共有两种情况,即相交和不相交。

相交分为三种情况(可以视为一条链表的尾部分别和另一条链表的不同部分相交):即头部、中间和尾部。

由图我们可以看出,若两条链表相交,他们的尾结点一定相同。

这可以作为我们判断两结点是否相交的判断点。

代码实现如下:

// 判断两个单链表是否相交---链表不带环 
int IsCrossWithoutCircle(PNode pHead1, PNode pHead2)//pHead1代表链表1,pHead2代表链表2
{
	PNode pTail1 = pHead1;//定义链表1的尾结点,并让其指向链表1的头结点
	PNode pTail2 = pHead2;//定义链表2的尾结点,并让其指向链表2的头结点


	//两链表只要有一个为空即不相交
	if (NULL == pTail1 || NULL == pTail2)
	{
		return 0;
	}
	//遍历链表1,找到尾结点
	while (pTail1->_pNext)
	{
		pTail1 = pTail1->_pNext;
	}


	//遍历链表2,找到尾结点
	while (pTail2->_pNext)
	{
		pTail2 = pTail2->_pNext;
	}


	//判断两条链表的尾结点是否相等
	if (pTail1 == pTail2)
	{
		return 1;//相等即相交,返回1
	}
	return 0;//不相等即不相交,返回0
}

构建的两条链表如下:

	//构建两条链表
	PNode pHead1;
	PNode pHead2;

	SListInit(&pHead1);//链表初始化
	SListPushBack(&pHead1, 1);//链表尾插
	SListPushBack(&pHead1, 2);
	SListPushBack(&pHead1, 3);
	
	SListInit(&pHead2);
	SListPushBack(&pHead2, 1);
	SListPushBack(&pHead2, 2);
	SListPushBack(&pHead2, 3);

	while (pHead1->_pNext)
	{
		pHead1 = pHead1->_pNext;
	}
	pHead1->_pNext = pHead2;

该种情况为相交的第三种情况,测试结果如下:


输出1,则其相交,其他情况不再一一描述。


带环的情况也比较多,不过经过分析也不会那么复杂。


接下来我们来画图进行分析



在画图过程中,我们可以发现:不会出现其中一条链表带环,且两条链表相交的情况。

由图我们可以得知,两个带环的链表相交分为,环内相交和环外相交两种。

在判断两链表是否相交的过程中,我们还需要实现判断链表是否带环,

判断链表是否带环:

1、定义两个指针,一个一次走两个结点(pFast),一个一次走一个结点(pSlow)

2、若有环,pFast会与pSlow相遇,此时返回两指针的地址;

     若无环,如果pFast==NULL,即可证明其无环,返回空指针

代码实现如下:

PNode IsListwithCircle(PNode pHead)
{
		PNode pFast = pHead;
	PNode pSlow = pHead;


	if (NULL == pHead)
	{
		return NULL;
	}


	while (pFast->_pNext)
	{
		pFast = pFast->_pNext->_pNext;
		pSlow = pSlow->_pNext;
		if (pFast == pSlow)
			return pFast;
	}
	return NULL;
}

接着判断两个链表是否相交:

大概思路就是:让两个链表的相遇点一个保持不动,一个往后走(每次走一步),若两个相遇点相遇,即可说明两条链表相交。

代码实现如下:

int IsCrossWithCircle(PNode pHead1, PNode pHead2)
{
	PNode pMeetNode1 = NULL;
	PNode pMeetNode2 = NULL;
	PNode pCur = NULL;
	
	if (NULL == pHead1 || NULL == pHead2)
	{
		return 0;
	}
	
	pMeetNode1 = IsListwithCircle(pHead1);
	pMeetNode2 = IsListwithCircle(pHead2);
	pCur = pMeetNode1;
	
	//其中一个链表带环或两条链表均不带环
	if (NULL == pMeetNode1 || NULL == pMeetNode2)
		return 0;

	//两条链表均带环
	while (pMeetNode1 != pMeetNode2)
	{
		pCur = pCur->_pNext;
		if (pCur == pMeetNode1)
			return 0;
	}
	return 1;
}

关于测试结果就不在展示了

判断两条链表是否相交经常会出现在面试题中,如果把图画出来写程序会更有思路。

欢迎交流~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值