单链表操作(2)(链表是否相交,是否有环)

文章介绍了如何处理单链表的相交问题和环问题。对于链表相交,通过计算两个链表的长度差,使用两个指针同步移动找到交点。而对于链表环问题,采用快慢指针方法判断环的存在,并计算入环节点的位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.链表的相交问题:

 链表的相交基本就上面俩种情况;但是对于这俩种情况来说,处理的方法都是想相同的

(1)如何判断是否有交点:

这就比较简单了,只需要定义一个指针,一直让他指到链表的最后一个节点,再来判断俩个指针是否相等。如果相等的话说明俩个链表一定是有交点的(不存在有交点但是最后一个节点不相同的问题,因为这是单链表,每个节点只能保存下一个节点的地址,不能保存俩个节点的地址)。

(2)如果有交点,返回相交的节点:

分别求出俩个链表的有效长度的差值n,然后定义指针p指向长链表,让p=p->next执行n次,在定义指针q指向短链表,俩个指针一起向后走,当他们相等的时候也就是相交的节点。

代码实现:

List* Intersect(List& Phead1, List& Phead2)
{
	if (Phead1.next == nullptr || Phead2.next == nullptr)
	{
		return nullptr;
	}
	int len1 = 0;
	int len2 = 0;
	List* p = Phead1.next;
	List* q = Phead2.next;
	for (p; p != nullptr; p = p->next)
	{
		++len1;
	}
	for (q; q != nullptr; q = q->next)
	{
		++len2;
	}
	if (p != q)                        //判断是否相交
	{
		return nullptr;
	}
	int n = len1 > len2 ? len1 - len2 : len2 - len1;
	if (len1 > len2)                                //找到相交节点
	{
		p = &Phead1;
		q = &Phead2;
		for (int i = 0; i < n; ++i)
		{
			p = p->next;
		}
		while (1)
		{
			p = p->next;
			q = q->next;
			if (p == q)
			{
				return p;         //return q也是一样的
			}
		}
	}
	if (len1 < len2)
	{
		p = &Phead1;
		q = &Phead2;
		for (int i = 0; i < n; ++i)
		{
			q = q->next;
		}
		while (1)
		{
			p = p->next;
			q = q->next;
			if (p == q)
			{
				return p;         //return q也是一样的
			}
		}
	}
}

2.链表环问题

判断链表是否有环,如果有的话返回入环节点:

判断是否有环,可以使用快慢指针,定义俩个指针,p, q。p每次往后走俩步,q走一步。如果链表有环的环,那么这俩个指针一定会相交。如果没有环,那么p一定是先走到终点的,也就是最后一个节点:

那找到相交节点后,就需要计算入环节点了。这里需要一些计算:

 我们设A到B的距离为x,也就是绿色的距离

B到C的距离为y,C到B的距离为z;由于他是单链表,所以从B到C和从C到B并不相同。

但由于我们需要求的是x;并且快指针所走的距离是慢指针的2倍

即ptwo=2pone;

所以:x+n*(y+z)+y=2x+2x+2*(n-k)*(y+z)

化简:x+y=2x+2y+(2*(n-k)-n)(y+z)

           x+y=(2k-n)(y+z)

           x=(2k-n)(y+z)-y

           x=(2k-n-1)(y+z)+z;

这时候我们可以看到,2k-n-1一定是个整数,并且大于等于0;

所以说,x这段距离等于整数倍的环(y+z)再加上z

也就是说用俩个速度一样的指针,一个从A开始跑,一个从C开始跑 

A跑到B的时候刚好另一个指针也跑到B

所以就能求出来入环的节点了

代码实现:

List* loop(List& phead)
{
	List* pone = &phead;
	List* ptwo = &phead;
	while (1)
	{
		pone = pone->next;
		ptwo = ptwo->next->next;
		if (ptwo == nullptr || ptwo->next == nullptr)
		{
			return nullptr;
		}
		else if (pone == ptwo)
		{
			break;
		}
	}
	pone = &phead;
	while (1)
	{
		if (pone == ptwo)
		{
			break;
		}
		pone = pone->next;
		ptwo = ptwo->next;
	}
	return pone;
}

以上就是单链表的相交问题和环问题。

感谢观看!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

g162512

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值