C语言强化(七)链表相交问题_5 找到两个有环链表的相交结点

原创 2015年04月27日 09:08:44

有环链表是否相交我们也可以判断了,剩下的就是获得有环链表相交结点


题目

给出俩个单向链表的头指针,比如 h1,h2,判断这俩个链表是否相交



解题步骤

  1. 判断两个【无环】链表是否相交
  2. 找到两个【无环】链表的相交结点
  3. 判断链表是否带环
  4. 判断两个【有环】链表是否相交
  5. 找到两个【有环】链表的相交结点

思路:
显然,有环链表的相交点其实就是环的入口
如图


所以 问题转为求环的入口

直接上理论,具体解释不难,纯粹是一道小学数学追赶问题

若在头结点和快慢指针相遇结点分别设一指针,同步(单步)前进,则最后一定相遇在环入口结点

关于快慢指针的介绍,请参考链表相交问题第三节


创建函数:获得有环链表入口

/*
获得有环链表入口
	若在头结点和相遇结点分别设一指针,同步(单步)前进,
	则最后一定相遇在环入口结点
*/
ListNode * getCircleListEnter(ListNode * head){
	if(head==NULL)
		return NULL;
	ListNode * node = ifCircle(head);
	if(node==NULL)
		return NULL;
	while(node!=NULL&&head!=NULL){
		if(node==head)
			return node;
		node=node->nextNode;
		head=head->nextNode;
	}
	return NULL;
}

源代码

#include <stdio.h>
#include<stdlib.h>
#include <iostream>


using namespace std;

/**
5.找到两个【有环】链表的相交结点
思路
	即找两个入口点
	若在头结点和相遇结点分别设一指针,同步(单步)前进,
	则最后一定相遇在环入口结点
*/

/**
链表结构体
*/
struct ListNode{
	int data;
	ListNode * nextNode;
	ListNode(ListNode * node,int value){
		nextNode=node;
		data=value;
	}
};

ListNode * L1;
ListNode * L2;

/**
判断链表是否有环
node  链表头指针

方法:用两个指针,一个指针步长为1,一个指针步长为2,若最后相遇,则链表有环
有环 返回两指针相遇位置
无环 返回NULL
*/
ListNode * ifCircle(ListNode * node){
	if(NULL==node)
		return false;
	ListNode * fast = node;
	ListNode * slow = node;
	while(NULL!=fast&&NULL!=fast->nextNode){
		fast=fast->nextNode->nextNode;//步长为2
		slow=slow->nextNode;//步长为1
		if(fast==slow){
			cout<<"链表有环"<<endl;
			return fast;
		}
	}
	cout<<"链表无环"<<endl;
	return NULL;
}

/*判断结点是不是在链表上
head  链表头
node  结点
*/
bool ifNodeOnList(ListNode * head,ListNode * node){

	if(node==NULL)
		return 0;
	//为防止有环链表无限遍历,首先进行有无环判断
	ListNode * circleNode = ifCircle(head);
	int count = 0;//经过重复结点的次数
	while(head!=NULL&&count<2){
		if(head==node)
			return 1;
		if(head==circleNode)
			count++;
		head=head->nextNode;
	}
	return 0;
}

//判断有环链表是否相交
bool ifCircleListCross(ListNode * L1,ListNode * L2){
	ListNode * node = ifCircle(L1);
	if(node!=NULL)
		return ifNodeOnList(L2,node);
	return 0;
}

/*
获得有环链表入口
	若在头结点和相遇结点分别设一指针,同步(单步)前进,
	则最后一定相遇在环入口结点
*/
ListNode * getCircleListEnter(ListNode * head){
	if(head==NULL)
		return NULL;
	ListNode * node = ifCircle(head);
	if(node==NULL)
		return NULL;
	while(node!=NULL&&head!=NULL){
		if(node==head)
			return node;
		node=node->nextNode;
		head=head->nextNode;
	}
	return NULL;
}

//创建有环链表
ListNode * createCircleList(){
	ListNode * node = new ListNode(NULL,0);
	ListNode * enter = node;
	node = new ListNode(node,1);
	node = new ListNode(node,2);
	enter->nextNode=node;
	node = new ListNode(node,3);
	node = new ListNode(node,4);
	return node;
}

//创建有环链表相交
void createCircleListCross(){
	L1 = new ListNode(NULL,0);
	ListNode * enter2 = L1;//L2的入口
	L1 = new ListNode(L1,1);
	L1 = new ListNode(L1,2);
	enter2->nextNode=L1;//L1的入口
	L1 = new ListNode(L1,3);
	L1 = new ListNode(L1,4);

	L2 = new ListNode(enter2,0);
	L2 = new ListNode(L2,1);
	L2 = new ListNode(L2,2);
}


//创建有环链表不相交
void createCircleListNotCross(){
	L1=createCircleList();
	L2=createCircleList();
}

void main()
{
	createCircleListCross();
	ListNode * node = getCircleListEnter(L1);
	cout<<"有环链表L1的入口(相交点1)"<<node->data<<endl;
	node = getCircleListEnter(L2);
	cout<<"有环链表L2的入口(相交点2)"<<node->data<<endl;
	system("pause");
}

至此,这道古老的链表相交问题终于讲完了,总结下思路

判断链表是否带环(第三节

不带环,用不带环的方法,判断是否相交、求相交点(第一节第二节

带环,用带环的方法,判断是否相交、求相交点(第三节第四节


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

C语言强化(七)链表相交问题_2 找到无环链表相交结点

上一节聊了判断两个【无环】链表是否相交,那么如果相交,怎么找到相交结点呢?...

C语言强化(七)链表相交问题_4 判断两个有环链表是否相交

上一节结束后,我们已经可以判断链表是否有环了,如果无环,那么按照前两节所讲的方法去判断链表是否相交以及获取相交结点,如果有环呢?怎么判断是否相交?...

3.6 判断两个无环链表是否相交 & 找出相交的第一个结点

1. 前言本文的一些图片, 资料 截取自编程之美2. 问题描述 3. 问题分析这两个问题也是非常经典的问题对于第一个问题 : 解法一 : 穷举, 穷举两个链表的各个元素, 判断有没有相同的结点解法...

判断链表有环没环及环的入口结点问题 和 判断两个链表是否相交

问题一:判断链表是否有环及入环结点问题 1、先判断是否有环 设置两个指针(fast, slow),初始值都指向头,slow每次前进一步,fast每次前进二步,如果链表存在环,则fast必定先进入环...

编程之美-编程判断两个链表(可能含环)是否相交以及相交的第一个结点

第三章 3.6 扩展题 扩展1 : 如何判断两个链表(含环)是否相交 扩展2 : 如何求出两个链表相交的第一个结点 假设两个链表分别为A,B链表 扩展1 :如何判断两个链表(含环)是否相交 ...

【面试题】-判断两个单链表是否相交并求出相交的第一结点

问题描述判断两个单链表是否相交,如果相交,给出相交的第一个点(假设两个链表都不存在环)。相交的链表示意图如下所示。 解题思路方法一两个没有环的链表如果是相交于某一结点,如上图所示,这个结点后面都是共...
  • zwhlxl
  • zwhlxl
  • 2015年05月15日 15:53
  • 1159

判断两个不带环链表是否相交?若相交,求入口点。

通常情况下,不带环的两个链表相交如上图所示。 方法一:先判断链表是否相交 ①若相交,那么两个链表的尾节点必然相同。则可以遍历两个链表,判断其尾节点。 ...
  • dycljj
  • dycljj
  • 2017年07月16日 18:29
  • 78

【数据结构】单链表—寻找两个相交链表中第一个公共结点 — 蛮力法 / 栈 / 指针先走

题目:输入两个链表,找到它们的第一个公共结点。思路一:蛮力法 在第一个链表上顺序遍历每一个结点,每遍历一个节点在第二个链表顺序遍历每一个结点,如果第二个链表上有一个结点和第一个链表上一样,说明两个链...

《C语言实现链表相交、带环问题》

例题://1.判断单链表是否带环?若带环,求环的长度?求环的入口点? //2.判断两个链表是否相交,若相交,求交点。(假设链表不带环) //3.判断两个链表是否相交,若相交,求交点。(假设链表可能带环...

判断有环链表是否相交

有环链表相交,首先两链表都要有环,一个有环一个无环不可能相交。有环链表相交有三种情况 则只需要判断是否共有一个环就行。 思路:分别取两链表上两个环内结点node1和node2,然后让node1遍历...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C语言强化(七)链表相交问题_5 找到两个有环链表的相交结点
举报原因:
原因补充:

(最多只允许输入30个字)