构建有序链表,有序链表的归并,反转链表

news2024/11/18 9:00:07

本次将对于构建有序链表,有序链表的归并,反转链表,进行一一介绍和代码分享。

首先是一些链表中的基本的函数:

Node* creatList()
{
    Node* headNode = (Node*)malloc(sizeof(Node));
    assert(headNode);
    headNode->next = NULL;
    return headNode;
}

Node* creatNode(Datatype data)
{
    Node* newNode = (Node*)malloc(sizeof(Node));
    assert(newNode);
    newNode->data = data;
    newNode->next = NULL;
    return newNode;
}

void traverseList(Node* headNode)
{
    Node* posNode = headNode->next;
    while (posNode != NULL)
    {
        printf("%d ", posNode->data);
        posNode = posNode->next;
    }
}

这里很基本,如果理解有困难,请从头学习链表。

以下是构建有序链表,也就是找到符合顺序的位置进行节点插入:

//构建有序链表:和构建顺序表一样,需要找到符合顺序的位置,然后插入元素
//核心是找到第一个比它大的节点,放到这个节点之前(双节点遍历)
void insertData(Node* headNode, Datatype data)
{
    Node* newNode = creatNode(data);
    Node* posNode = headNode->next;
    Node* preNode = headNode;
    //assert(posNode);
    //当前面节点的数据小于data的时候,继续向后走
    while (posNode!= NULL && posNode->data <= data)
    {
        posNode = posNode->next;
        preNode = preNode->next;
    }
    //特殊的情况分析:(短路现象)
    //pos在第一个节点,第一个节点为空,那么说明只有表头,连接表头和newNode
    if (posNode == NULL&&posNode == headNode->next)
    {
        headNode->next= newNode;
    }
    //pos不在第一个节点,但是pos指向空,
    //pos指向最后一个节点的后面一个,也就是还有没有找到大于data的:
    // 说明没有大于data的节点,所以将data与最后连接即可
    else if (posNode == NULL && posNode != headNode->next)
    {
        preNode->next = newNode;
    }
    //找到了位置,插入在pos的前面
    else
    {
        newNode->next = posNode;
        preNode->next = newNode;
    }
}

这个过程和顺序表的构建流程基本相同,比较简单,所以不做过多解释。

接下来是单链表的翻转:

void reverseList(Node* headNode)
{
   //对于1个表头,1个节点;1个表头,2个节点的链表不需要进行翻转
   if (headNode->next == NULL || headNode->next->next == NULL)
   {
       return;
    }
    Node* posNode = headNode->next;
    Node* preNode = NULL;
    Node* sucNode = headNode->next->next;
    while (sucNode != NULL)
    {
        //指向改变
        posNode->next = preNode;
        //整体向后移动
        preNode = posNode;
        posNode = sucNode;
        sucNode = sucNode->next;
    }
    //最后一步改变指向方向
    posNode->next = preNode;
    //将表头与完成反转的第一个节点相连接
    headNode->next = posNode;
}

以下是逐步的过程模拟:结合代码中的注释和过程一一对应更容易理解,其中preNode,sucNode分别是posNode的前驱和后继节点。

示例

假设我们有以下的单链表:

headNode -> 1 -> 2 -> 3 -> 4 -> NULL

我们希望反转后得到:

headNode -> 4 -> 3 -> 2 -> 1 -> NULL

分析执行过程

  1. 初始化指针:
    • posNode 指向第一个元素(1)。
    • preNode 为 NULL(因为没有前驱节点)。
    • sucNode 指向第二个元素(2)。
  2. 进入循环,当 sucNode 不为 NULL 时:
    • 改变 posNode(当前节点)的 next 指针,使其指向前驱节点 preNode
    • 更新 preNode 为当前的 posNode
    • 更新 posNode 为当前的 sucNode
    • 更新 sucNode 为 posNode 的下一个节点。

这个过程会一直持续到 sucNode 为 NULL,即到达链表的末尾。

  1. 在循环结束后,执行以下操作:
    • 将最后一个节点(posNode)的 next 指针指向 preNode
    • 将头节点的 next 指针指向反转后的第一个节点(posNode)。

最后,两个有序链表的归并:

//有序链表的归并:
void mergeList(Node* newHeadNode, Node* head1, Node* head2)
{
    Node* up = head1->next;
    Node* down = head2->next;
    Node* temp = newHeadNode;
    assert(up && down);
    while (up != NULL && down != NULL)
    {
        if (up->data < down->data)
        {
            temp->next= up;
            up = up->next;
        }
        else
        {
            temp->next = down;
            down = down->next;
        }
        temp = temp->next;
    }
    //up结尾,down没结尾
    if (up == NULL && down != NULL)
    {
        temp->next = down;
    }
    //down结尾,up没结尾
    else if (up != NULL && down == NULL)
    {
        temp->next = up;
    }
    //没有两个同时结尾的情况
}

示例和分析执行过程:

假设我们有以下两个有序链表:

head1: 1 -> 3 -> 5
head2: 2 -> 4 -> 6

调用 mergeList(newHeadNode, head1, head2); 后,我们希望得到以下合并后的链表:

newHeadNode -> 1 -> 2 -> 3 -> 4 -> 5 -> 6

执行过程:

  1. up 指向 1down 指向 2temp 指向 newHeadNode
  2. 因为 1 < 2,所以 temp->next = up;,然后 up 移动到 3temp 移动到 1
  3. 现在 up 指向 3down 指向 2
  4. 因为 2 < 3,所以 temp->next = down;,然后 down 移动到 4temp 移动到 2
  5. 重复这个过程,直到 up 或 down 为 NULL
  6. 在本例中,当 up 指向 5 且 down 指向 4 时,因为 4 < 5down 指向的节点会被插入到新链表中。
  7. 当 down 遍历到 NULL 时,up 还有节点 5 和 6。因此,将 up 指向的剩余链表直接连接到新链表的末尾。

对于链表的归并,代码虽然简单,但要理解其中的流程是极为关键的,本次的分享结束,希望对你有帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1610345.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

汽车摄像头匿名化处理解决方案,保护信息的安全性和隐私性

随着智能交通和自动驾驶技术的迅猛发展&#xff0c;汽车摄像头已成为现代汽车不可或缺的一部分&#xff0c;摄像头所捕捉的图像信息也引发了日益严峻的信息安全问题。如何在充分利用摄像头功能的同时&#xff0c;保障个人隐私和信息安全&#xff0c;已成为企业亟待解决的问题。…

CPRI协议理解——帧格式中的计数标识

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 CPRI协议理解——帧格式中的计数标识 前言帧格式中的计数标识总结 前言 CPRI协议是一个流式协议&#xff0c;数据不间断的传输&#xff0c;在我们要了解CPRI到底要传输种类繁…

HDMI to TYPE-C芯片|HDMI2.0转TYPE-C转接器方案|CS5802设计方案|ASL CS5802

CS5802输入端可以是1080P、4K30、4K60HZ这三种规格,输出的接口可以是TYPE-C信号接口,或者是TYPE-C信号接口,输入端HDMI由4路信号组成&#xff0c;支持1.62Gbps、2.7Gbps、5.4Gbps链路速率。内置可选SSC功能可降低EMI的干扰状况。 ASL CS5802芯片概述&#xff1a; 符合HDMI规范…

抖去推短视频矩阵系统----源头开发

为什么一直说让企业去做短视频矩阵&#xff1f;而好处就是有更多的流量入口&#xff0c;不同平台或账号之间可以进行资源互换&#xff0c;最终目的就是获客留咨&#xff0c;提单转化。你去看一些做得大的账号&#xff0c;你会发现他们在许多大的平台上&#xff0c;都有自己的账…

基于Python利用zhconv模块进行简繁体字转换

在处理中文文本时&#xff0c;简繁体字之间的转换是一项常见的任务。Python提供了许多库来实现这个目的&#xff0c;其中之一就是zhconv。zhconv是一个Python库&#xff0c;提供了简体字和繁体字之间的转换功能。本教程将向你展示如何使用zhconv模块来实现简繁体字的互转&#…

【MATLAB】App 设计 (入门)

设计APP 主界面 函数方法 定时器 classdef MemoryMonitorAppExample < matlab.apps.AppBase% Properties that correspond to app componentsproperties (Access public)UIFigure matlab.ui.FigureStopButton matlab.ui.control.ButtonStartButton matlab.ui.cont…

用户行为分析模型实践(四)—— 留存分析模型

作者&#xff1a;vivo 互联网大数据团队- Wu Yonggang、Li Xiong 本文是vivo互联网大数据团队《用户行为分析模型实践》系列文章第4篇 -留存分析模型。 本文详细介绍了留存分析模型的概念及基本原理&#xff0c;并阐述了其在产品中具体实现。针对在实际使用过程问题&#xff0…

力扣---从前序与中序遍历序列构造二叉树

给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一棵树的中序遍历&#xff0c;请构造二叉树并返回其根节点。 示例 1: 输入: preorder [3,9,20,15,7], inorder [9,3,15,20,7] 输出: [3,9,20,null,null,15,7]示…

面试Spring框架

什么是Spring框架&#xff1f; Spring框架是一个开源的Java应用程序框架&#xff0c;提供了综合的基础设施支持&#xff0c;用于开发Java企业应用程序。它涵盖了从基本的核心容器到全面的企业服务&#xff0c;可以用于构建任何规模的应用程序。 Spring框架的核心特性是什么&am…

深度解析 Spring 源码:三级缓存机制探究

文章目录 一、 三级缓存的概述二、 三级缓存的实现原理2.1 创建Bean流程图2.2 getBean()2.3 doGetBean()2.4 createBean()2.5 doCreateBean()2.4 getSingleton() 三、 三级缓存的使用场景与注意事项3.1 在实际开发中如何使用三级缓存3.2 三级缓存可能出现的问题及解决方法 一、…

黑马---苍穹外卖总结上

1.功能模块 1.1 管理端功能 员工登录/退出 , 员工信息管理 , 分类管理 , 菜品管理 , 套餐管理 , 菜品口味管理 , 订单管理 &#xff0c;数据统计&#xff0c;来单提醒。 模块描述登录/退出内部员工必须登录后,才可以访问系统管理后台员工管理管理员可以在系统后台对员工信息进…

数据结构学习--环形链表

环形链表 我们在判断一个链表是否是环形的&#xff0c;即首尾相连&#xff0c;我们可以以使用快慢指针&#xff0c;如果快指针能再次追上慢指针&#xff0c;就说明该链表是环形的&#xff0c;这边可以举个操场跑步的例子&#xff0c;当操场是环形的&#xff0c;跑的快的&#…

Ansible组件说明

1.Ansible Inventory 工作当中有不同的业务主机&#xff0c;我们需要在把这些机器信息存放在inventory里面&#xff0c;ansible默认的inventory的文件是/etc/ansible/hosts&#xff0c;也可以通过ANSIBLE_HOSTS环境变量来指定或者运行ansible和ansible-playbook的时候用-i参数临…

泛微E9开发 快速隐藏明细表列

快速隐藏明细表列 1、隐藏列方法&#xff08;不作用&#xff0c;一直隐藏&#xff09; 在实际运用中&#xff0c;用户不需要但是需要间接使用的列&#xff0c;我们可以通过右击该列-【列自定义属性】-在“列自定义属性”菜单中启用“隐藏列”功能。 根据该方法设置的前端页…

纯js图片上传插件

目录标题 一、效果预览二、使用简单三、完整代码&#xff08;一&#xff09;index.html&#xff08;二&#xff09;css&#xff08;三&#xff09;js四、附带后台上传文件代码 一、效果预览 支持多图片上传&#xff0c;删除、预览。 二、使用简单 导入依赖&#xff08;需要…

视觉化数据的艺术:掌握Matplotlib基础绘图

Matplotlib基础绘图 文章目录 Matplotlib基础绘图1.基础流程2.绘图设置3.动态rc参数4.pyplot的基础图表函数 安利 1.基础流程 1.导入模块。绘图之前&#xff0c;需要先导入包含相应函数的模块。 2.创建画布与创建子图。第一部分主要是构建出一张空白的画布&#xff0c;如果需要…

Elastic 网络爬虫:为你的网站添加搜索功能

作者&#xff1a;来自 Elastic Lionel Palacin 为了演示如何使用 Elastic 网络爬虫&#xff0c;我们将以一个具体的网站为例&#xff0c;讲解如何在该网站上添加搜索功能。我们将探讨发现网站的方法&#xff0c;并利用 Elastic 网络爬虫提供的功能&#xff0c;以最佳方式准备待…

springboot+ssm基于Java的小型企业银行账目管理系统代码Lw

本毕业设计课题要求学生基于软件工程方法&#xff0c;根据课题的需求&#xff0c;给出小型企业银行账目管理系统概要设计、详细设计、数据库的设计以及系统实现和测试&#xff0c;并撰写规范的毕业设计说明书。该系统的主要模块有&#xff1a;系统管理、帐目管理、查询统计、用…

如何创建响应式HTML电子邮件模板

在这个适合初学者的指南中&#xff0c;你将学习如何创建一个响应式电子邮件模板。你将跟随逐步说明以及代码片段设计一个在任何设备上都看起来很棒的电子邮件模板。 这个项目非常适合渴望掌握电子邮件设计基础的新手&#xff01; &#xff08;本文视频讲解&#xff1a;java56…

抖店严查违规店铺!老商家下台,新手正是入驻时机!

哈喽~我是电商月月 抖店一直在严查违规店铺&#xff0c;很多新手都在犹豫不前&#xff0c;不知道要不要去做抖音小店 以为是抖音平台在“想方设法”克扣商家钱财&#xff0c;开店都是坑&#xff1f; 要这样想&#xff0c;那就大错特错了&#xff01; 抖店整改&#xff0c;把…