IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 关于链表以及链表相交问题 -> 正文阅读

[数据结构与算法]关于链表以及链表相交问题

在c语言中,链表是一个重要的板块,也是一个较难的板块,这里我这下我平时写链表题目的一些小心得。

1:链表的是由一个一个节点相连而成,每一个节点都由数据域以及指针域组成,这里有个重要的地方是指针域应该是指向自己的一个指针变量,如下:

struct node{

datatype? ?data;

struct? node *next;

}*Node;

此处的datatype指的是数据的类型,可以是int,float之类的,也可以是自定义的机构体类型。

2:在最开始的时候,需要为链表的头结点开辟一个空间,如下:

struct Node head,

head=(node*)malloc(sizeof(node));

head->next=NULL;

这样就开辟了一个头结点,这个头结点没有数据,只是用来指向链表而已,方便后续对链表操作而已。

3:之后一个需要解决的操作是为链表添加后续指针,这里就需要开辟一个新的空间,并且没添加一次就需要开辟一次,如下:

struct Node p,s;

s=head;

p=(node*)malloc(sizeof(node));

scanf(“%d”,p->data);

s->next=p;

s=p;

这里用的尾插法,需要注意的是,当你不想继续输入数据或者已经跳出循环后,要将s->next设为NULL,否则这个链表就出错啦(我之前也在这犯过错)

7aefc0c7fd4a44d2860ab9bbd8e004db.jpg

之后就是输出了,可以用while循环,操作如下:

struct node e;? ? ? ? ? ? ? ? ? ? ? ?

e=head->next;//此处因为head没有数据,所

//以指向next

while(e!=NULL)

{

printf(“%d”,e->data);

e=e->next;

}

这样就可以啦,一个新鲜的链表就出来了

8d00dd078c054634a5ff9e216f7e65a0.jpg

但是你以为能够熟练创建一个链表就已经结束了吗?nonono,还有好多难题呢,这里有一个问题:如何查看两个单链表是否相交,并且返回相交节点?

这个时候大家估计都在想,两个链表相交还不简单?直接找到最末端的地方,看地址相不相同不就行了吗?确实,这是一般的思路,但是,要是这两个链表都成环了呢?你怎么知道他们相交了呢?

01b0fe55a62f460cab49386e8e2c1e4e.jpg

?想迷糊了吧。

其实也很简单。

首先,这问题分三种情况讨论:

1)两个链表都没成环,那么就直接比较最末端的地址就是了,相同则相交

2)一个成环,一个未成环,这种情况是绝对不会相交的,大家可以自己想想为什么。

3)一种是两个都成环了,而这里又分相交与没相交两种情况,而相交又分两种情况,是在入环前相交还是在入环后相交的?

把这三种情况考虑到了后再去做题。

首先是如何查看链表是否成环:

这就要利用快慢指针了,让快慢指针依次遍历这个链表,若是会相遇,则一定成环,然后让慢指针继续遍历,快指针从头重新遍历,但是快指针的速度和慢指针一样,它们之后一定会在入环节点相遇,然后返回这个入环节点就是了,思路很简单,代码也是:

struct Node findloop(struct Node head)

{

        if(head==NULL)
        return NULL;
        if(head->next==head)
        return head;
? ? ? ? struct Node fast,slow;
        fast=head->next;
        slow=head;
        int flag=1;//flag=1则表示为成环
        while(fast!=NULL&&fast->next!=NULL)
            {
                fast=fast->next;
                slow=slow->next;
                if(slow==fast)
                {
                    flag=0;
                    break;//相等就跳出循环
                }
            }
        if(flag==0)
            {
                fast=head; 
                while(slow!=fast)
                {
                    slow=slow->next;
                    fast=fast->next;
                }
                return fast;//返回成环结点    
            }
        else    
        return false;

}

这里是我借鉴了其他大佬的代码写出来的,大家可以画图来自己思考为什么这样写。

?9a4b209399ce40189bf50cb8c6c0fd49.jpg?

? ? ? ?这里就找到了入环结点,当两个链表都返回了一个结点说明都成环,一个为NULL一个有结点就可以直接说明未相交了,而都为NULL就说明都不成环。

接着我们来检测未成环的链表是否相交

检测代码如下:

struct Node fun(struct Node head1,struct Node head2)

{? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

   struct Node s1,s2;
    s1=head1->next;
    s2=head2->next;
    while(s1->next!=NULL)
    s1=s1->next;
    while(s2->next!=NULL)
    s2=s2->next;
    if(s1==s2)
        return 1;
    else
        return 0;

}? ? ? ? ? ? ? ?

? ? ?

若是检测出有相同,就要去寻找相交结点在哪儿,代码如下:

struct Node fun(struct Node head1,struct Node head2)
{ 
    struct Node s1,s2;

    s1=head1->next;

    s2=head2->next;

? ? ? ? ? ?    int n=0;

? ? ?     ?while(s1!=NULL)

            {

                s1=s1->next;

                n++;
            }? ? ? ? ? ? ? ??

            while(s2!=NULL)

            {

                s2=s2->next;

                n--;

            }

            s1=n>0?head1:head2;//让s1指向长的链表。

            s2=(s1==head1)?head2:head1;//s2指向s1之外的链表

            n=fabs(n);

            while(n!=0)

            {
    
                s1=s1->next;

            n--;
            }

            while(s1!=s2)

            {

                //两个结点相等了就跳出循环

                s1=s1->next;

                s2=s2->next;


            }

            

                    return s1;

}

解决完未成环的链表相交问题后,就得解决成环链表相交问题了。

首先需要判断成环链表是否相交,利用上面的求入环结点的函数,判断入环结点是否相同,相同则是在成环之前就相交了,若是成环之前就相交,就将入环结点看成是NULL来找相交结点

代码如下:

struct Node find1(struct Node head1,struct Node head2,struct Node loop)
{
        struct Node s1,s2;
        s1=head1->next;
        s2=head2->next;
        int n=0;
        while(s1!=loop)
        {
            s1=s1->next;
            n++;
        }
        while(s2!=loop)
        {
            s2=s2->next;
            n--;
        }
        s1=n>0?head1:head2;
        s2=(s1==head1)?head2:head1;
        n=fabs(n);
        while(n!=0)
           {
                n--;
                s1=s1->next;
            }
        while(s1!=s2)
        {
            s1=s1->next;
            s2=s2->next;
        }
            return s1;
}    

之后就是另一种情况,那就是成环后相交;

这种情况需要和成环不相交进行区别,所以需要将两个链表的入环结点来判断,使得一个入环结点不动,另一个移动,若是相遇到了,则是成环后相交,若是转了一圈还是没找到,那就是成环后不相交;

代码如下:

struct Node (struct Node head1,struct Node head2,struct Node loop1,struct Node loop2)
{
        struct Node s1,s2,s3;
         s1=loop1;
         s2=loop2;
         s3=loop1->next;
         while(s3!=s1)
            {
                    s3=s3->next;
                    if(s3==s2)
                        return s2;//若是s3在循环路上遇到了s2说明相交,返回一个就行
             }
        return NULL;
           
}

以上就是链表相交问题的大概思路了,新人还不是很熟练,希望大佬们多多指点。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-04-01 23:38:43  更:2022-04-01 23:39:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 9:42:54-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码