判断两个链表是否相交

如何判断两个链表是否相交并求出相交点 排除链表存在环的情况此情况的意思就是普通的单链表是否相交问题。 相交是什么意思?注意不是单纯的节点的数值域相等,相交的意思是两个链表的部门节点的是同一个,就是这些节点为这两个链表共有。 链表的定义参照:http://blog.youkuaiyun.com/dawn_after_dark/article/details/73610674方法一我们根据上图可以发现,链表相交之后,后面的部分节点全部共用,所以 阅读详情

判断两个链表是否相交  

2012-01-09 10:37:03|  分类: 默认分类 |  标签: |字号大中小 订阅

给出两个单向链表的头指针,判断这两个链表是否相交,如果相交给出相交的第一个结点

一、两个链表均不含有环

链表相交如下图

 

判断两个链表是否相交 - 枫叶 - 枫叶

 方法一:直接法

   直接判断第一个链表的每个结点是否在第二个链表中,时间复杂度为O(len1*len2),耗时很大

方法二:利用计数

如 果 两个链表相交,则两个链表就会有共同的结点;而结点地址又是结点唯一标识。因而判断两个链表中是否存在地址一致的节点,就可以知道是否相交了。可以对第一 个链表的节点地址进行hash排序,建立hash表,然后针对第二个链表的每个节点的地址查询hash表,如果它在hash表中出现,则说明两个链表有共 同的结点。这个方法的时间复杂度为:O(max(len1+len2);但同时还得增加O(len1)的存储空间存储哈希表。这样减少了时间复杂度,增加 了存储空间。

以链表节点地址为值,遍历第一个链表,使用Hash保存所有节点地址值,结束条件为到最后一个节点(无环)或Hash中该地址值已经存在(有环)。

再遍历第二个链表,判断节点地址值是否已经存在于上面创建的Hash表中。

这个方面可以解决题目中的所有情况,时间复杂度为O(m+n),m和n分别是两个链表中节点数量。由于节点地址指针就是一个整型,假设链表都是在堆中动态创建的,可以使用堆的起始地址作为偏移量,以地址减去这个偏移量作为Hash函数

方法三

两个没有环的链表相交于一节点,则在这个节点之后的所有结点都是两个链表所共有的。如果它们相交,则最后一个结点一定是共有的,则只需要判断最后一个结点是否相同即可。时间复杂度为O(len1+len2)。对于相交的第一个结点,则可求出两个链表的长度,然后用长的减去短的得到一个差值 K,然后让长的链表先遍历K个结点,然后两个链表再开始比较。还可以这样:其中一个链表首尾相连,检测另外一个链表是否存在环,如果存在,则两个链表相交,而检测出来的依赖环入口即为相交的第一个

/************************************************************************/
/* 两个不含环的单链表的相交
   相交指的是结点的地址相同,而不是结点的值相同                        */
/************************************************************************/
#include<iostream>
#include<malloc.h>
#include<stdlib.h>
#define  ERROR 0
using namespace std;

struct LinkList//链表结构体
{
 int m_nValue;
 LinkList *next;
};

void InsertList(LinkList *&list)//建立一个链表
{
    LinkList *head;
    LinkList *newNode;
    int data;
    
    head=list;
    while(head->next)
     head=head->next;
  
    while(1)//链尾法构造链表
    {  
   cin>>data;
   if(data==0)break;   

  newNode=(LinkList *)malloc(sizeof(LinkList));
  if(!newNode)exit(ERROR);
        newNode->m_nValue=data;
  newNode->next=NULL;

  head->next=newNode;
        head=newNode;
  head->next=NULL;
  }


}
void Traverse(LinkList *list)//输出链表
{
 LinkList *p;
 p=list->next;
 while(p)
 {
  cout<<" "<<p->m_nValue<<"    address= "<<p<<endl;
  p=p->next;
 }
}

int main()
{
 LinkList *first,*second;
 LinkList *fhead,*shead,*h1,*h2,*p,*q;

 int flen=0,slen=0,len;
 first=(LinkList *)malloc(sizeof(LinkList));
 first->next=NULL;
 second=(LinkList *)malloc(sizeof(LinkList));
 second->next=NULL;

 InsertList(first);//构造第一个链表
 cout<<endl;
 InsertList(second);//构造第二个链表

   /////////////////////////////////////////////////
   //将第一个链表中从第四个结点起链接到第二个链表,构造两个相交的链表
 p=second;
   while(p->next)
    p=p->next;//找到第二个链表的尾结点
 
   q=first;
   for(int i=0;i<4;i++)
       q=q->next;//找到第一个链表的第四个结点
   p->next=q;//插入到第二个链表中
  //////////////////////////////////////////////////
 Traverse(first);
 cout<<endl;
    Traverse(second);
 cout<<endl;

    h1=first->next;
 fhead=first;
 while(fhead->next)//遍历链表到表尾 (执行length1次,记n2次)

 {
  fhead=fhead->next;
  flen++;
 }

    h2=second->next;
 shead=second;
 while(shead->next)//遍历链表到表尾, (执行length2次,记n1次)
 {
  shead=shead->next;
  slen++;
 }
  if(fhead==shead)//最后一个结点的地址相同,则相交
 { 
  cout<<"两链表相交"<<endl;

 if(flen>=slen)//求两个链表长度的差值
 {
  len=flen-slen;
  while(len--) //遍历差值个步长 (执行abs(length1-length2)次)

           h1=h1->next;  
 }
 else
 {
  len=slen-flen;
  while(len--)
   h2=h2->next; 
 }

 while(1)
 {
  
  if(h1==h2)//两个链表中地址相同的结点   (最多执行的次数为:min(length1,length2))

  {
    cout<<"第一个相交的结点:"<<h1->m_nValue;
   break;
  }
  else if(h1->next&&h2->next)
  {
   h1=h1->next;
   h2=h2->next;
  } 
 }
 }
 else
  cout<<"两链表不相交"<<endl;

  
}

结果:

 
判断两个链表是否相交 - 枫叶 - 枫叶
 二、链表中含有环
链表中有环如下图:
判断两个链表是否相交 - 枫叶 - 枫叶
1.链表中是否有环的判断
可以设置两个指针(fast,slow),初始值均指向头,slow每次向前一步,fast每次向前两步;
如果链表中有环,则fast先进入环中,而slow后进入环中,两个指针在环中必定相遇;
如果fast遍历到尾部为NULL,则无环
2.链表有环,判断环的入口点
  当fast若与slow相遇时,slow肯定没有走遍历完链表,而fast已经在环内循环了n圈(1<=n)。假设slow走了s步,则fast走了2s步(fast步数还等于s 加上在环上多转的n圈),设环长为r,则:

2s = s + nr
s= nr

设整个链表长L,入口环与相遇点距离为x,起点到环入口点的距离为a。
a + x = nr
a + x = (n – 1)r +r = (n-1)r + L - a
a = (n-1)r + (L – a – x)

(L – a – x)为相遇点到环入口点的距离,由此可知,从链表头到环入口点等于(n-1)循环内环+相遇点到环入口点
 
因而,可以在链表头,相遇点分别设定一个指针,每次各走一步,两个指针必定相遇,则相遇第一点为环入口点。
LinkList *  ListLoop(LinkList *list) //判断一个链表中是否有环
{
 int isLoop=0;
 LinkList *fast,*slow;
 fast=list;
 slow=list;
 while(fast&&fast->next)
 {
  slow=slow->next;
  fast=fast->next->next;//fast每次两步,slow每次一步
  if(fast==slow) //当两指针相等时,判断链表中有环
  {
   isLoop=1;
   break;
  }
 }
  if(isLoop==1)//链表中有环时
  {
   slow=list;
 while(slow!=fast)//一个头指针,一个相遇点指针,两个第一次相等时为环入口点
 {
  slow=slow->next;
  fast=fast->next;
 }
 return slow;
  }
  else
  {
   cout<<"链表中没有环";
   return NULL;
  }
} 
当两个链表中有环时,相交的判断:
(1)首先分别找出两个链表入环的第一个结点记为p1,p2
 (2)如果p1==p2,说明两个链表在入环之前或入环的第一个结点相交;则此 时可以转为两个链表均不带环相交的判断,把p1,p2当作最后的末尾结点
(3)如果p1!=p2,此时两个链表可能完全不相交;也可能两个链表完全共有同一个环。
此时,判断 p1->next与p2->next是否相等,如果相等则两链表完全共环;如果不相等,则完全不相交。
 
当一个链表中有环,一个链表中没有环时,两个链表必不相交。
《编程之美》——编程判断两个链表是否相交 问题: 给出两个链表的头指针,判断这两个链表是否相交。假设两个链表均不带环。 分析与解法:【解法一】 如果两个链表都无环,则可以把第二个链表接在第一个链表后面,如果得到的链表有环,则说明这两个链表相交。这里如果有环,则第二个链表的表头一定在环上,只需要从第二个链表开始遍历,看是否会回到起点即可判断。假设两个链表长度分别为m和n,则时间复杂度为O(m+n)。 【解法二】 若两个链表都无环且交 阅读详情

相关推荐

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

题目:输入两个链表的头节点,判断这两个链表是否存在相交 链表的定义如下: typedef int Elemtype; typedef struct ListNode { Elemtype data;//值域 ListNode *m_pNext;//指针域 }ListNode,*PListNode; 看到这个题目后大多数的人的第一反应应该就是,判断这两个链表的任意一个节点的指针是...

genzld的博客 4893

如何判断两个链表是否相交并找出交点

解题思路 情况1:两个链表均不含有环 1、直接法 采用暴力的方法,遍历两个链表,判断第一个链表的每个结点是否在第二个链表中,时间复杂度为O(len1*len2),耗时很大。 2、hash计数法 如 果 两个链表相交,则两个链表就会有共同的结点;而结点地址又是结点唯一标识。因而判断两个链表中是否存在地址一致的节点,就可以知道是否相交了。可以对第一 个链表的节点地址进行hash排序,建立hash表,然后针对第二个链表的每个节点的地址查询hash表,如果它在hash表中出现,则说明两个链表有共 同的结点。这个方法

onlymayao的博客 6786

数据结构—判断两个链表是否相交,寻找两个链表的相交节点

【题目】 判断两个链表(链表可以有环,可以无环)是否相交,若相交,则返回相交节点,不相交则返回null 1.判断两个链表是否相交 【思路】 两个链表分三种情况: ①两个链表均为非环链表; ②两个链表一个为环,一个非环; ③两个链表均为环 第一种情况非环链表根据链表的定义,只需比较两个链表尾节点是否相同,若相同则一定相交,不同则一定不相交; 第二种情况由于链表的next指针永远

ningzn的博客 565

判断两个单链表是否相交

文章转自: http://c.biancheng.net/data_structure/linear_list/ 所谓相交,是指有公共的部分,而 2 个单链表相交,则意味着它们有公共的节点,公共节点的数量可以是 1 个或者多个。 单链表是线性表的一种,如果我们将 2 个单链表看做 2 条线段的话,下图则模拟了 2 条线段相交的所有可能情况。 结合“单链表中每个节点有且仅有 1 个指针域”的特性,上图所示的这 3 种情况中,只有第 2 种情况符合单链表的特性,另外 2 种情况则破坏了此特性。因此要验证 2

Lianuuu的博客 3416

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

问题描述判断两个单链表是否相交,如果相交,给出相交的第一个点(假设两个链表都不存在环)。相交的链表示意图如下所示。 解题思路方法一两个没有环的链表如果是相交于某一结点,如上图所示,这个结点后面都是共有的。所以如果两个链表相交,那么两个链表的尾结点的地址也是一样的。程序实现时分别遍历两个单链表,直到尾结点。判断尾结点地址是否相等即可。时间复杂度为O(L1+L2)。方法二代码实现方法一void Is_

zengwh 6112

C++判断两个链表是否相交算法

1.判断一个链表是否相交,若相交,求交点(假设链表带环) 2.具体思路如下图所示 既然已经分析清楚,那么代码就很好实现了. Node* IsHaveCrossNode(Node* head1,Node* head2) { assert(head1); assert(head2); Node* meetNode1 = IsC...

程序猿老樊的博客 1381

如何判断两个链表是否相交?如果相交求交点

问题描述:一个比较经典的问题,判断两个链表是否相交,如果相交找出他们的交点。(注意两个单链表相交不会出现X型交叉——单链表,每个节点只有一个指针域)。第一种情况:两个链表均不含有环解题思路:1、直接法:采用暴力的方法,遍历两个链表,判断第一个链表的每个结点是否在第二个链表中,时间复杂度为O(len1*len2),耗时很大;顺序查询到第一个在第二个链表种的节点即是两个链表的交点。2、先遍历第一个链表...

Gandoph的博客 1万+

微信小程序消息推送实战:从模板消息到订阅消息的进阶指南

本文详细解析了微信小程序消息推送的核心机制,重点对比了模板消息与订阅消息的差异与应用场景。模板消息适用于支付成功等强即时性业务回执,而订阅消息则需用户授权,更适合物流提醒等可预期通知。文章提供了从授权、配置到发送的完整实战指南,并分享了常见的避坑技巧与性能优化建议,帮助开发者构建高效、合规的用户触达体系。

weixin_29231027的博客 594

判断两个单向链表是否相交

给定两个(单向)链表,判定它们是否相交并返回交点。请注意相交的定义基于节点的引用,而不是基于节点的值。换句话说,如果一个链表的第k个节点与另一个链表的第j个节点是同一节点(引用完全相同),则这两个链表相交。 首先最容易想到暴力搜寻,对A链的每一个节点,都对B链表进行遍历搜索看是否相同 public ListNode getIntersectionNode(ListNode headA, Lis...

CodeHunter_qcy 2118

Visual Studio 6.0 镜像下载全指南:从企业版到中文版

本文提供Visual Studio 6.0企业版和中文版的镜像下载全指南,包括详细版本解析、已验证的下载链接及校验信息。针对现代系统的安装技巧和兼容性处理方案,帮助开发者高效获取并运行这一经典开发工具,特别适合维护遗留系统的专业人员。

weixin_33712987的博客 1002

【FPGA】AD9653设计和调试总结

基于FPGA的AD9653设计,设计思路,注意事项

weixin_41246509的博客 7590

如何判断两个有环链表是否相交

如何判断两个有环链表是否相交 问题 ​ 如何判断两个有环链表是否相交,相交则返回第一个相交节点,不相交则返回null。 思路 ​ 我们已经得到了两个链表各自的第一个入环节点,假设链表1的第一个入环节点为loop1,链表2的第一个入环节点为loop2。具体如下: ​ 1.如果loop1 == loop2,拓扑结构如图: ​ 该情况下,考虑链表1从头开始到loop1这一段与链表2从头开始到loop2...

勇敢前进的ACMer 2150

【数据集】中国大气污染物数据集CHAP(1km空间分辨率)-韦晶团队

中国大气污染物数据集CHAP(1km空间分辨率)-韦晶团队

WW、forever的博客 2595

判断两个单链表是否相交,相交则返回两个链表相交的结点

判断两个链表是否相交,相交则返回两个链表相交的结点 为了让判断两个链表是否相交,我们首先要做的就是将两个链表进行"对齐".(两个链表相交也就是说,从相交的结点开始,后面两个链表内容相同). 所以我们的思路就是首先通过链表遍历,求出两个链表的长度,得到其差值. 创建两个指针分别指向这两个链表的头位置. 然后对较长的链表开始从头遍历差值部分. 接下来让两个指针一起向前走,直至相遇则得到两链表相交结点,...

persistence_Y的博客 399

【自然语言处理】情感分析(一):基于 NLTK 的 Naive Bayes 实现

朴素贝叶斯(Naive Bayes)分类器可以用来确定输入文本属于某一组类别的概率。例如,预测评论是正面的还是负面的。它是 “朴素的”,它假设文本中的单词是独立的(但在现实的自然人类语言中,单词的顺序传达了上下文信息)。尽管有这些假设,但朴素贝叶斯在使用少量训练集预测类别时具有很高的准确性。

Data · Model · Agent · Repeat 2173

SAP 消息号T-CODE

SAP消息号修改汇总 确实有很多消息是可以修改的 FI: oBA5|oFMG|oFPM MM: oMRM|oKZZ|oMT4|oMCQ|o04C| SD: oVAH(V4)|oVM1(VL) CO:  oPR4_ACT|oPR4_CK|oPR4_CKML|oPR4_CKPF|oPR4_KKA|oPR4_KKP|oPR4_KKS| oPR4_KKS1|oPR4_P

heng0757的专栏 1万+
上一篇: c++(重载、覆盖、隐藏)
下一篇: 输入一个整形数组,数组里有正数也有负数,数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和
DSIslander
博客等级 码龄20年 14粉丝 2原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值