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

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

题目

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

解题步骤

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

思路

  • 遍历的过程中记录链表的长度L1和L2(假设L1>L2)
  • 遍历找到第一个链表中的第L1 - L2节点,
  • 链表一从第L1-L2个节点开始遍历,链表二从第一个节点遍历,相当于两链表从与相交点距离相同的两个地点同时出发
  • 每次前进一步
  • 直到找到第一个相同的节点,则可以认为两个链表存在相交节点,
  • 该点即为第一个相交节点

思路图解

源代码

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

using namespace std;

/**
2.找到两个【无环】链表的相交结点
思路
	遍历的过程中记录链表的长度L1和L2(假设L1>L2)
	然后遍历找到第一个链表中的第L1 - L2节点,
	然后链表一从第L1-L2个节点开始遍历,
	链表二从第一个节点遍历,每次前进一步,
	直到找到第一个相同的节点,则可以认为两个链表存在相交节点,
	并且该点即为第一个相交节点
*/

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

ListNode * L1;
ListNode * L2;

/**
获取链表长度
*/
int getListLength(ListNode * head){
	int i =0;
	if(head==NULL)
		return 0;
	while(head->nextNode!=NULL){
		head=head->nextNode;
		i++;
	}
	return i;
}

/**
获取指定位置的链表结点
*/
ListNode * getThatListNode(ListNode * head,int pos){
	int i =0;
	if(head==NULL)
		return NULL;
	while(head->nextNode!=NULL){
		head=head->nextNode;
		i++;
		if(pos==i)
			return head;
	}
	return NULL;
}

/**
获取俩无环链表相交结点
L1:较长链表
L2:较短链表
*/
ListNode * getNoCircleListCrossNode(ListNode * L1,ListNode * L2){
	ListNode * L_Long;
	ListNode * L_Short;
	int start;
	int length1 = getListLength(L1);
	int length2 = getListLength(L2);
	if(length1>=length2){
		L_Long=L1;
		L_Short=L2;
		start=length1-length2;
	}else{
		L_Long=L2;
		L_Short=L1;
		start=length2-length1;
	}
	L_Long=getThatListNode(L_Long,start);
	while(L_Long->nextNode!=NULL&&L_Short->nextNode!=NULL){
		if(L_Long==L_Short)
			return L_Long;
		L_Long=L_Long->nextNode;
		L_Short=L_Short->nextNode;
	}

	return NULL;
}

//测试无环相交
void testCross(){

	//相交段
	ListNode * node = new ListNode(NULL,0);
	node = new ListNode(node,1);
	node = new ListNode(node,2);
	node = new ListNode(node,3);
	//在此处开始相交
	L1 = new ListNode(node,11);
	L2 = new ListNode(node,21);

	//不相交段
	L1 = new ListNode(L1,12);
	L1 = new ListNode(L1,13);

	L2 = new ListNode(L2,22);
	L2 = new ListNode(L2,23);
	L2 = new ListNode(L2,24);
	L2 = new ListNode(L2,25);
}

void main()
{
	testCross();
	//int length1 = getListLength(L1);
	//cout<<length1<<endl;
	//ListNode * node = getThatListNode(L1, 3);
	//cout<<node->data<<endl;
	ListNode * node = getNoCircleListCrossNode(L1,L2);
	if(node!=NULL)
		cout<<node->data<<endl;
	else
		cout<<"无相交点"<<endl;
	system("pause");
}

前两篇讨论的前提都是链表是无环的,但是如果链表有环呢?下一篇,聊。

时间: 2024-08-12 18:16:13

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

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

有环链表是否相交我们也可以判断了,剩下的就是获得有环链表相交结点 题目 给出俩个单向链表的头指针,比如 h1,h2,判断这俩个链表是否相交 解题步骤 判断两个[无环]链表是否相交 找到两个[无环]链表的相交结点 判断链表是否带环 判断两个[有环]链表是否相交 找到两个[有环]链表的相交结点 思路: 显然,有环链表的相交点其实就是环的入口 如图 所以 问题转为求环的入口 直接上理论,具体解释不难,纯粹是一道小学数学追赶问题 若在头结点和快慢指针相遇结点分别设一指针,同步(单步)前进,则最后一定相遇

C语言强化(七)链表相交问题_1 判断无环链表相交

从此篇博文开始,讲解一道古老的链表相交问题,共五篇 题目 给出俩个单向链表的头指针,比如 h1,h2,判断这俩个链表是否相交 解题步骤 判断两个[无环]链表是否相交 找到两个[无环]链表的相交结点 判断链表是否带环 判断两个[有环]链表是否相交 找到两个[有环]链表的相交结点 此篇先从最简单的判断两个[无环]链表是否相交开始,顺便介绍一下链表的基础知识,方便一些对链表不太了解的同学学习. 基础知识 什么是链表? 链表是一种物理存储单元上非连续.非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指

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

上一节结束后,我们已经可以判断链表是否有环了,如果无环,那么按照前两节所讲的方法去判断链表是否相交以及获取相交结点,如果有环呢?怎么判断是否相交? 题目 给出俩个单向链表的头指针,比如 h1,h2,判断这俩个链表是否相交 解题步骤 判断两个[无环]链表是否相交 找到两个[无环]链表的相交结点 判断链表是否带环 判断两个[有环]链表是否相交 找到两个[有环]链表的相交结点 思路 对于有环的链表,只要它们相交,则带环的那一段必定完全重复.所以我们只需要在链表一上找到环上的一个结点,判断该结点是否在链

C语言强化(七)链表相交问题_3 判断链表是否带环

前两篇讨论的前提都是链表是无环的,但是如果链表有环呢? 显然,如果链表有环,那么之前的寻找链表尾结点的函数将陷入死循环,之前的算法也将崩掉. 所以对于链表相交的问题,首先要判断的是链表是否有环. 题目 给出俩个单向链表的头指针,比如 h1,h2,判断这俩个链表是否相交 解题步骤 判断两个[无环]链表是否相交 找到两个[无环]链表的相交结点 判断链表是否带环 判断两个[有环]链表是否相交 找到两个[有环]链表的相交结点 思路 用两个指针,一个指针步长为1,一个指针步长为2,若最后相遇,则链表有环

C语言强化(一)二叉排序树转成排序的双向链表

几乎每一位码士的编程起点都是C,在玩过了Java.C#.PHP.Python之后,重回C语言,又是什么样的一种感觉呢? 此篇博文作为 [C语言强化]系列文章的第一篇,来聊聊曾让许多码士抓耳挠腮的二叉树. 通过这道题,你可以掌握 如何创建二叉树 如何遍历二叉树 如何创建二叉链表 怎样使用递归算法 这是一道非常老土但又十分经典的数据结构题,或许很多人会说自己之前已经做过了,但又有多少人回过头来做的时候,可以不借助任何参考资料把解题思路写出来? 题目要求:二叉排序树->双向链表排序 不能新增结点,只能

Python与数据结构[0] -&gt; 链表[2] -&gt; 链表有环与链表相交判断的 Python 实现

链表有环与链表相交判断的 Python 实现 目录 有环链表 相交链表 1 有环链表 判断链表是否有环可以参考链接, 有环链表主要包括以下几个问题(C语言描述): 判断环是否存在: 可以使用追赶方法,定义两个指针slow和fast,分别以1步和2步前进,若存在环则两者会相遇,否则fast遇到NULL时则退出: 获取环的长度:若存在环,则以相遇点为起点,fast和slow再次开始前进,第二次碰相遇slow走过的步数(1圈)即为环长度: 找出入环点:相遇点到连接点的距离 = 头指针到连接点的距离,因

使用C语言描述静态链表和动态链表

静态链表和动态链表是线性表链式存储结构的两种不同的表示方式. 静态链表的初始长度一般是固定的,在做插入和删除操作时不需要移动元素,仅需修改指针,故仍具有链式存储结构的主要优点. 动态链表是相对于静态链表而言的,一般地,在描述线性表的链式存储结构时如果没有特别说明即默认描述的是动态链表. 下面给出它们的简单实现,关于线性表更为详尽的C语言的实现,可以参考 http://www.cnblogs.com/choon/p/3876606.html 静态链表 #define _CRT_SECURE_NO_

数据结构C语言实现——线性链表

declaration.h #ifndef DECLARATION_H_INCLUDED #define DECLARATION_H_INCLUDED #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 #define ElemType int typedef ElemType* Triplet; typedef int Status; type

C语言实现单链表节点的删除(带头结点)

我在之前一篇博客<C语言实现单链表节点的删除(不带头结点)>中具体实现了怎样在一个不带头结点的单链表的删除一个节点,在这一篇博客中我改成了带头结点的单链表.代码演示样例上传至 https://github.com/chenyufeng1991/DeleteLinkedList_HeadNode.删除类型有两种: (1)删除某个位置pos的节点: (2)推断x值是否在链表中,若存在则删除该节点: 核心代码例如以下: //删除某个位置pos的节点 Node *DeletePosNode(Node