线性表之单链表详解

一、概念

        链表作为线性表的链式存储结构,将线性表L = (a0,...ai-1,ai,ai+1...an-1) 中的各元素分布在存储器的不同存储块,称为结点。结点之间通过指针建立联系

 其中:data作为数据域next作为指针域指向ai的直接后继ai+1结点

由此也能看出,头结点的重要性,有了头结点,其他结点都很方便找出

特别地,头结点的数据域无意义,尾结点的指针域为NULL

 二、结构模型

typedef int data_t;

typedef struct node{
    data_t data;
    struct node *next;
}LinkList,*pLinkList;

//因为动态内存方便我们按需开辟,所以我们经常使用如下方式创建结点
pLinkList p;
p = (pLinkList)malloc(sizeof(LinkList));

 三、链表运算操作


typedef int data_t;

typedef struct node{
    data_t data;
    struct node *next;
}LinkList,*pLinkList;

pLinkList list_create(void);//创建空链表
int list_tail_insert(pLinkList Head, data_t value);//尾插结点
pLinkList list_getpos(pLinkList Head, int pos);//按位置寻找结点
int list_insert_byPos(pLinkList Head, data_t value, int pos);//按位置插入结点
int list_delete_byPos(pLinkList Head, int pos);//按位置删除结点
int list_show(pLinkList Head);//打印链表
pLinkList list_free(pLinkList Head);//释放链表
int list_reverse(pLinkList Head);//链表反转
pLinkList list_FindMaxTwo(pLinkList Head);//找相邻结点数据之和最大的结点

四、实现原理

4.1创建空链表

因为头结点在链表当中是非常重要的,创建一个空链表当然是围绕它来展开

  • 申请空间
  • 初始化
pLinkList list_create()
{
    pLinkList Head;
    //创建头结点并为其申请内存
    Head = (pLinkList)malloc(sizeof(LinkList));
    if(Head == NULL)
    {
        printf("list_creat:malloc failed!\n");
        return NULL;
    }
    //初始化头结点
    Head->data = 0;
    Head->next = NULL;

    
    return Head;
}

4.2尾部插入结点

尾部插入实际上还是寻找尾结点(特征是指针域为空),同时插入新的结点势必需要为其分配内存+初始化

  • 新建结点(申请内存)
  • 初始化
  • 寻找尾结点
  • 插入新结点
int list_tail_insert(pLinkList Head, data_t value)
{
    pLinkList new;
    pLinkList Index = Head;

    if(Head == NULL)
    {
        printf("list_tail_insert:Head is NULL!\n");
        return -1;
    }
    //新建结点
    new = (pLinkList)malloc(sizeof(LinkList));
    if(new == NULL)
    {
        printf("list_tail_insert:malloc failed!\n");
        return -1;
    }
    //赋值结点
    new->data = value;
    new->next = NULL;
    //寻找尾结点
    while(Index->next != NULL)
    {
        Index = Index->next;
    }
    //插入结点
    Index->next = new;    
    return 1;
}

头部插入其实很简单,新结点先指向结点0,头结点再指向新结点即可(操作顺序不可变!

4.3按位置寻找结点

注意是线性表,L = (a0,...ai-1,ai,ai+1...an-1)。头结点就看作-1即可

  • 对寻找位置进行检查
    • <-1     没必要进行
    • == -1  返回头结点
  • 进行循环寻找,链表指针从头结点开始移动,需要移动pos+1次

//传入-1 返回头结点 传入0返回第一个结点 依次类推
pLinkList list_getpos(pLinkList Head, int pos)
{
    pLinkList Index = Head;
    int i;

    if(Head == NULL)
    {
        printf("list_getpos:Head is NULL!\n");
        return NULL;
    }
    if(pos < -1)
    {
        printf("list_getpos:pos is invalid!\n");
        return NULL;
    }
    if(pos == -1)
    {
        return Head;
    }
    //因为总共需要移动pos+1次 所以从头结点开始遍历
    i = -1;
    while(i++ < pos)//这里pos肯定是0以上的值
    {
        Index = Index->next;
        if(Index == NULL)//找到尾结点
        {
            printf("list_getpos:pos is invalid!\n");
            break;
            return NULL;
        }
    }

    return Index;
}

4.4按位置插入结点

按位置插入结点,是要取代原来位置的结点,势必需要先找到它的前一个结点,这里用指针pre寻找,通过4.3实现的函数获得

int list_insert_byPos(pLinkList Head, data_t value, int pos)
{
    pLinkList new;
    pLinkList pre = list_getpos(Head,pos-1);//插入位置的前一个结点

    if(Head == NULL)
    {
        printf("list_insert_byPos:Head is NULL!\n");
        return -1;
    }
    if(pre == NULL)//pos过大导致前结点都找不到 这里即使前一个结点是尾结点也没事,追加即可
    {
        printf("list_insert_byPos:find pre failed!\n");
        return -1;
    }
    //创建结点
    new = (pLinkList)malloc(sizeof(LinkList));
    if(new == NULL)
    {
        printf("list_insert_byPos:malloc failed!\n");
        return -1;
    }
    new->data = value;
    //更新指向
    new->next = pre->next;//新结点指向pre的下一个结点
    pre->next = new;      //pre指向new

    return 1;  
}

4.5按位置删除结点

删除结点要注意的是,链表中每个结点都是使用的动态内存同时涉及指针,及时释放和赋值为空是避免野指针的好习惯!

此外,删除结点也需要找到它的前一个,因为删除的结点撤走后,不能影响其他结点的连接

int list_delete_byPos(pLinkList Head, int pos)
{
    pLinkList pre = list_getpos(Head,pos-1);//插入位置的前一个结点
    pLinkList delete;

    if(Head == NULL)
    {
        printf("list_delete_byPos:Head is NULL!\n");
        return -1;
    }
    if(pre == NULL || pre->next == NULL)//pos过大导致前结点都找不到 或者 pre是尾结点那就没必要删除了
    {
        printf("list_delete_byPos:delete pos is invalid!\n");
        return -1;
    }
    //更新指向 
    delete = pre->next;
    pre->next = delete->next; //相当于pre->next = pre->next->next 为了方便释放空间 delete保存
    
    //再释放要删除的结点的空间
    printf("delete pos:%d,delete:data:%d\n",pos,delete->data);
    free(delete);
    delete = NULL;

    return 1;
}

4.6打印链表

int list_show(pLinkList Head)
{
    pLinkList Index = Head;

    if(Head == NULL)
    {
        printf("list_show:Head is NULL!\n");
        return -1;
    }
    //遍历链表并且打印
    while(Index->next != NULL)
    {
        printf("%d ",Index->next->data);
        Index = Index->next;
    }
    puts("");

    return 1;
}

4.7释放链表

pLinkList list_free(pLinkList Head)
{
    pLinkList WaittoFree;

    if(Head == NULL)
    {
        printf("list_free:Head is NULL!\n");
        return NULL;
    }

    while(Head != NULL)
    {
        WaittoFree = Head;
        Head = Head->next;//先移动头结点
        free(WaittoFree);//再释放
    }

    return NULL;
}

4.8链表反转

思路是把链表一分为二,循环把list2中的结点插入到list1中,直到遍历到list2中的尾结点

int list_reverse(pLinkList Head)
{
    pLinkList list1 = Head;
    pLinkList list2;
    pLinkList Index;//用于执行插入

    //参数检查: 链表非法或只有头结点或只有一个结点0
    if(Head == NULL || Head->next == NULL || Head->next->next == NULL)
    {
        printf("list_reverse:Head doesn't need to be reversed!\n");
        return -1;
    }
    //list2 接手 结点0之后的所有结点
    list2 = Head->next->next;
    //list1断开结点0和其他结点的连接
    list1->next->next = NULL;

    //遍历list2
    while(list2 != NULL)
    {
        Index = list2;//获得list2的第一个结点
        list2 = list2->next;//list2断开第一个结点

        Index->next = list1->next;//list2的第一个结点指向list1的结点0
        list1->next = Index;//list2的第一个结点成为list1新的结点0
    }

    return 1;
}

4.9寻找相邻结点数据之和最大

pLinkList list_FindMaxTwo(pLinkList Head)
{
    int CurMax;
    pLinkList p,q;//用于在链表中前后移动
    pLinkList ret;

    if(Head == NULL)
    {
        printf("list_FindMaxTwo:Head is NULL!\n");
        return NULL;
    }
    //只有头结点或者只有结点0
    if(Head->next == NULL || Head->next->next == NULL)
    {
        printf("list_FindMaxTwo:list is not enough!\n");
        return Head;
    }
    //如果只有结点0和结点1 返回结点0即可
    if(Head->next->next->next == NULL)
    {
        return Head->next;
    }

    //初始化p、q、最大值
    p = Head->next;//指向结点0
    q = Head->next->next;//指向结点1  相当于q = p->next;
    ret = p;
    CurMax = p->data + q->data;

    //遍历链表
    while(q->next != NULL)
    {
        //先移动p、q再进行比较
        p = p->next;
        q = q->next;
        if((p->data + q->data) > CurMax)
        {
            CurMax = p->data + q->data;
            ret = p;
        }
    }

    return ret;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

启明智显ZX7981PC:5G时代的新选择,全屋网络无缝覆盖

在这个飞速发展的5G时代&#xff0c;每一个细微的科技进步都在推动着我们的生活向更加智能、便捷的方向发展。近日&#xff0c;启明智显再次引领科技潮流&#xff0c;正式发布其最新的5G CPE产品——ZX7981PC。作为继7981PG与7981PM之后的又一次迭代升级&#xff0c;ZX7981PC凭…

ubuntu检测是否已安装nvidia驱动以及产品类型

nvidia-sminvidia-smi 是 NVIDIA 提供的一个命令行工具&#xff0c;用于查看和管理 NVIDIA GPU 的状态。当你运行 nvidia-smi 命令时&#xff0c;它会显示当前系统中所有 NVIDIA GPU 的状态信息&#xff0c;包括 GPU 的使用率、温度、内存使用情况等。 有8个GPU nvcc -V查看c…

Introduction to NoSQL Systems

What is NoSQL NoSQL database are no-tabular非數據表格 database that store data differently than relational tables 其數據的存儲方式與關係型表格不同 Database that provide a mechanism機制 for data storage retrieval 檢索 that is modelled in means other than …

Javaweb web后端maven介绍作用安装

自动导入到这个项目 src是源代码 main主程序&#xff0c;核心代码 java是Java源代码 resources是项目配置文件 test测试相关的 maven概述 介绍 依赖在本地仓库查找&#xff0c;如果本地仓库有&#xff0c;用本地仓库的依赖&#xff0c;本地没有&#xff0c;连接中央仓库&…

MinIO分布式文件存储

一、分布式文件系统 问题引出 对于一个网站系统&#xff0c;若为降低成本投入&#xff0c;将文件存储服务和网站系统部署在同一台服务器中&#xff0c;访问量不大&#xff0c;基本不会有问题&#xff0c;但访问量逐渐升高&#xff0c;网站文件资源读取逐渐频繁&#xff0c;单…

SQL Server:只有MDF文件,如何附加数据库

第一步&#xff1a;先新建一个同名数据库&#xff0c;然后停止sql服务&#xff0c;删除新建数据库.ldf文件。 第二步&#xff1a;将要附加的数据库的.mdf文件覆盖刚新建的.mdf文件&#xff0c;并重启sql服务。 第三步&#xff1a;这时数据库DATA目录下只有一个.mdf文件&#xf…

《HTML 的变革之路:从过去到未来》

一、HTML 的发展历程 图片: HTML 从诞生至今&#xff0c;经历了多个版本的迭代。 &#xff08;一&#xff09;早期版本 HTML 3.2 在 1997 年 1 月 14 日成为 W3C 推荐标准&#xff0c;提供了表格、文字绕排和复杂数学元素显示等新特性&#xff0c;但因实现复杂且缺乏浏览器…

机器视觉与OpenCV--01篇

计算机眼中的图像 像素 像素是图像的基本单位&#xff0c;每个像素存储着图像的颜色、亮度或者其他特征&#xff0c;一张图片就是由若干个像素组成的。 RGB 在计算机中&#xff0c;RGB三种颜色被称为RGB三通道&#xff0c;且每个通道的取值都是0到255之间。 计算机中图像的…

网络安全创新实验

一、网络拓扑设计 二、网络主机概况 本实验一共包含4台虚拟机&#xff0c;分别为攻击机attacker&#xff0c;网关gateway&#xff0c;内网普通用户主机pc&#xff0c;内网服务器server&#xff0c;四台主机的详细信息如下表所示&#xff1a; 名称操作系统IP地址网络模式作用攻…

y3编辑器教学5:触发器2 案例演示

文章目录 一、探索1.1 ECA1.1.1 ECA的定义1.1.2 使用触发器实现瞬间移动效果 1.2 变量1.2.1 什么是变量1.2.2 使用变量存储碎片收集数量并展现 1.3 if语句&#xff08;魔法效果挂接&#xff09;1.3.1 地形设置1.3.2 编写能量灌注逻辑1.3.3 编写能量灌注后&#xff0c;实现传送逻…

016 在路由器上配置 DHCP

配置路由器端口IP地址 将路由器的端口地址配置好&#xff0c; 左边的网络地址是 192.168.1.0 右边的网络地址是 192.168.2.0 配置路由器的DHCP服务 打开命令窗口&#xff0c;进入特权模式 进入全局配置 conf t创建一个DHCP地址池&#xff1b; po1 是地址池的名称&#xf…

恋爱脑学Rust之并行之旅:Rayon介绍和使用

文章目录 一、开启爱情的依赖之旅&#xff08;安装 Rayon&#xff09;二、甜蜜瞬间的并行享受&#xff08;基本数据并行操作&#xff09;&#xff08;一&#xff09;共享美好时光&#xff08;par_iter 方法&#xff09;&#xff08;二&#xff09;分块珍藏回忆&#xff08;par_…

【数据库系列】PostgreSQL 数据库连接

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

中介者模式的理解和实践

一、中介者模式概述 中介者模式&#xff08;Mediator Pattern&#xff09;&#xff0c;也称为调解者模式或调停者模式&#xff0c;是一种行为设计模式。它的核心思想是通过引入一个中介者对象来封装一系列对象之间的交互&#xff0c;使得这些对象不必直接相互作用&#xff0c;从…

吸烟抽烟行为识别数据集-超高识别率,支持YOLO,COCO,VOC格式的标注,10162张各种姿势场景下的吸烟图片

吸烟抽烟行为识别数据集-超高识别率&#xff0c;支持YOLO&#xff0c;COCO,VOC格式的标注&#xff0c;10162张各种姿势场景下的吸烟图片 数据集分割 训练组91&#xff05; 9279图片 有效集5&#xff05; 507图片 测试集4% 376图片 预处理 自动定…

【开源】基于SpringBoot框架的房屋租赁系统 (计算机毕业设计)+万字毕业论文 T020

系统合集跳转 源码获取链接 一、系统环境 运行环境: 最好是java jdk 1.8&#xff0c;我们在这个平台上运行的。其他版本理论上也可以。 IDE环境&#xff1a; Eclipse,Myeclipse,IDEA或者Spring Tool Suite都可以 tomcat环境&#xff1a; Tomcat 7.x,8.x,9.x版本均可 操作系统…

C++20 标准概念

1. 所有标准概念的概述 “类型和对象基本概念”表列出了类型和对象的基本概念。 “范围、迭代器和算法概念”表列出了范围、视图、迭代器和算法的概念。 “辅助概念”表列出的概念主要用作其他概念的构建块&#xff0c;通常不会让应用程序开发者直接使用。 头文件和命名空间 …

git的卸载与安装

目录 一、Git的卸载 二、Git的安装 2.1.1 官网下载 2.1.2 镜像下载 ​编辑 2.2 安装 2.3 检验否安装成功 三、Git使用配置 一、Git的卸载 1.找到程序&#xff0c;卸载程序 2.找到Git&#xff0c;右键卸载 卸载完成&#xff01; 二、Git的安装 2.1.1 官网下载 网址&…

科技赋能电影,互动电影开启电影新格局

近年来&#xff0c;科技赋能电影&#xff0c;让电影越来越精彩&#xff0c;也越来越多元。层出不穷的新技术新类型&#xff0c;不断丰富着电影视听语言的表现形式&#xff0c;也为观众带来更多具有交互性和个性化的观影体验。进昂互动科技在推出全球首部院线互动电影《夜班》之…

python 下载 b站视频 和音频

video_bvid&#xff1a; import os import requests import json import re from bs4 import BeautifulSoup import subprocess # from detail_video import video_bvid# video_bvid 是一个从外部得到的单个视频ID video_bvid BV1cx421Q7veclass BilibiliVideoAudio:def __in…