数据结构-单链表

文章目录

    • 单链表概念
    • 链接存储方法
    • 头指针head和终端结点
    • 链接过程
    • 单链表的优缺点:
    • 实现
    • 代码一览


单链表概念

链表中的数据是以结点来表示的,每个结点的构成:元素(数据元素的映象) + 指针(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。以“结点的序列”表示线性表称作线性链表(单链表),单链表是链式存取的结构。

链接存储方法

链接方式存储的线性表简称为链表(Linked List)。 链表的具体存储表示为: ①
用一组任意的存储单元来存放线性表的结点(这组存储单元既可以是连续的,也可以是不连续的) ②
链表中结点的逻辑次序和物理次序不一定相同。为了能正确表示结点间的逻辑关系,在存储每个结点值的同时,还必须存储指示其后继结点的地址(或位置)信息(称为指针(pointer)或链(link))
链式存储是最常用的存储方式之一,它不仅可用来表示线性表,而且可用来表示各种非线性的数据结构。
结点结构:
在这里插入图片描述

data域–存放结点值的数据域 next域–存放结点的直接后继的地址(位置)的指针域(链域)
链表通过每个结点的链域将线性表的n个结点按其逻辑顺序链接在一起的,每个结点只有一个链域的链表称为单链表(Single Linked
List)。

头指针head和终端结点

单链表中每个结点的存储地址是存放在其前趋结点next域中,而开始结点无前趋,故应设头指针head指向开始结点。链表由头指针唯一确定,单链表可以用头指针的名字来命名。
终端结点无后继,故终端结点的指针域为空,即NULL。

链接过程

从逻辑上:
在这里插入图片描述
从物理上:
在这里插入图片描述

单链表的优缺点:

1、优点:

插入和删除操作方便,在单链表中,插入和删除节点时,只需修改相邻节点的游标即可,不需要移动大量数据,因此操作效率较高。适合动态存储,单链表可以随时插入和删除节点,因此适合动态存储数据。空间利用率高,单链表不需要连续的存储空间,因此可以更有效地利用内存空间。

2、缺点:

查找效率低,在单链表中,查找某个元素需要从头节点开始遍历整个链表,因此查找效率较低。
需要额外的空间存储游标,单链表需要额外的空间存储游标,这会增加内存空间的消耗。实现复杂度较高,相比数组等数据结构,单链表的实现复杂度较高,需要维护节点的引用关系。

实现

一.思路
1.利用结构体来储存数据和指针(结构体能够存储不同类型数据)
2.每增加一个数据就通过malloc函数来扩展一个空间
3.通过多文件的方式来实现
4.我们实现打印、扩容、尾插、头插、尾删、头删接口函数
二.框架
结构体创建、一些定义:

#include<stdio.h>
#include<stdlib.h>//动态内存函数的头文件
typedef int SLTDataType;//类型定义
struct SListNode
{SLTDataType data;//数据struct SListNode* next;//链接点
};
typedef struct SListNode SLTNode;//类型定义

主函数:

void  Test() {SLTNode* plist = NULL;//头指针初始化  因为开始是没有数据}
int main() {Test();//调用函数return 0;
}

三.接口函数的实现
1.打印函数:
(1)参数:结构体指针类型(接收头指针),由于不需要改变头指针,所以传一个头指针变量过来就行
(2)迭代:将后一个链接的指针变量 next 传给指针phead来找到下一个结点
代码实现:

void SListPrint(SLTNode* phead) {//打印函数//由于不需要改变头指针,所以传一个头指针变量过来就行了while (phead != NULL) {//将phead不是空指针之前的数据打印printf("%d->", phead->data);//打印数据phead = phead->next;//迭代}printf("NULL");//最后打印指向的NUll
}

2.扩容函数:
(1)我们通过malloc函数来实现扩容
(2)参数:插入的数据
(3)返回类型:返回扩建的空间指针变量
(4)过程:在扩容后将插入的数据存储到这个空间里。并把指针变量置空
代码实现:

SLTNode* uuu(SLTDataType x) {//扩容和储存数据SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));newnode->data = x;//储存数据newnode->next = NULL;//将扩容和的链接点置空return newnode;//放回这个空间的地址
}

3.尾插函数:
有两种情况:
(1)头指针为空,此时将扩建的第一个空间直接当头指针
在这里插入图片描述
(2)头指针不为空,此时将我们要通过头指针找到最后一个结点,再用这个结点来链接我们扩建的空间
在这里插入图片描述
注意:
1.在实现这个过程可能会改变头指针,所以传参需要使用传址调用

2.第二种情况不要改变头指针

代码实现:

void SListPushBack(SLTNode** pphead, SLTDataType x) {//尾插
//注意:这里需要传参需要进行传址调用SLTNode* newnode = uuu(x);//插入一个数据需要再创建一个新的空间if (*pphead == NULL)//判断是否是第一种情况*pphead = newnode;else{SLTNode* cat = *pphead;//防止头指针被改变while(cat->next!=NULL){//找到最后一个结点cat = cat->next;//迭代}cat->next = newnode;//将扩展的空间连接在最后一个结点的next上}
}

检查:
我们尾插 1、2

SListPushBack(&plist, 1);
SListPushBack(&plist, 2);
SListPrint(plist);

在这里插入图片描述

4.头插函数:
(1)我们直接将创建的空间的next与第一个结点连接即可
在这里插入图片描述
注意:在实现这个过程会改变头指针,所以传参需要使用传址调用
代码实现:

void SListPushFront(SLTNode** pphead, SLTDataType x) {头插SLTNode* newnode = uuu(x);//扩建空间newnode->next = *pphead;//与第一个结点连接即头指针*pphead = newnode;//将头指针改为头插的空间
}

检查:
我们头插一个 0

void  Test() {SLTNode* plist = NULL;SListPushBack(&plist, 1);SListPushBack(&plist, 2);SListPushFront(&plist, 0);SListPrint(plist);
}

运行结果:
在这里插入图片描述
5,头删函数:
(1)这个我们不用创建新的空间但是要释放空间。释放函数 ferr()
(2)我们可以创建一个新的指针变量来接收第一个结点的next(第二个结点的地址),然后将第一个结点释放掉,再然后将新的指针变量当作头指针
(3)在实现这个过程会改变头指针,所以传参需要使用传址调用
代码实现:

void SListPopFront(SLTNode** pphead) {//头删SLTNode* next = (*pphead)->next;//创建一个新的指针变量来接收第一个结点的next(第二个结点的地址)free(*pphead);//释放*pphead = next;//重新设置头指针
}

检查:
头删一个数据:

void  Test() {SLTNode* plist = NULL;SListPushBack(&plist, 1);SListPushBack(&plist, 2);SListPushFront(&plist, 0);SListPopFront(&plist);SListPrint(plist);
}

运行结果:
在这里插入图片描述
6.尾删函数:
分三种情况:
(1)没有结点
返回NULL
(2)有一个结点
将其直接释放,并置空
(3)多个结点
我们要创建两个新的变量分别来找倒数第一和第二个结点,释放最后一个结点倒数,第二个结点next置空

代码实现:

void SListPopBack(SLTNode** pphead) {//尾删if (*pphead == NULL)//当为空是直接返回空return;else if ((*pphead)->next == NULL) {//只有一个结点时,直接释放掉pphead并将其置空free(*pphead);*pphead = NULL;}else {//多个结点SLTNode* cat = *pphead;//为了不改变头指针,创建一个新的变量SLTNode* cat1= NULL;//用于找到倒数第二个结点,最后将其next置空while (cat->next != NULL) {//找最后一个结点cat1 = cat;cat = cat->next;}free(cat);//释放最后一个结点cat1->next = NULL;//倒数第二个结点next置空}
}

检查:
尾删一个数据

void  Test() {SLTNode* plist = NULL;SListPushBack(&plist, 1);SListPushBack(&plist, 2);SListPushFront(&plist, 0);SListPopFront(&plist);SListPopBack(&plist);		SListPrint(plist);
}

运行结果:
在这里插入图片描述

代码一览

SList.h:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>//动态内存函数的头文件
typedef int SLTDataType;//类型定义
struct SListNode
{SLTDataType data;//数据struct SListNode* next;//链接点
};
typedef struct SListNode SLTNode;//类型定义// 不会改变链表的头指针,传一级指针
void SListPrint(SLTNode* phead);// 可能会改变链表的头指针,传二级指针
void SListPushBack(SLTNode** pphead, SLTDataType x);//尾插
void SListPushFront(SLTNode** pphead, SLTDataType x);//头插
void SListPopFront(SLTNode** pphead);头删
void SListPopBack(SLTNode** pphead);//尾删

SList.c:

#define _CRT_SECURE_NO_WARNINGS
#include"SList.h"void SListPrint(SLTNode* phead) {//打印函数//由于不需要改变头指针,所以传一个头指针变量过来就行了while (phead != NULL) {//将phead不是空指针之前的数据打印printf("%d->", phead->data);//打印数据phead = phead->next;//迭代}printf("NULL");//最后打印指向的NUll
}SLTNode* uuu(SLTDataType x) {//扩容和储存数据SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));newnode->data = x;//储存数据newnode->next = NULL;//将扩容和的链接点置空return newnode;//放回这个空间的地址
}void SListPushBack(SLTNode** pphead, SLTDataType x) {//尾插SLTNode* newnode = uuu(x);if (*pphead == NULL)*pphead = newnode;else{SLTNode* cat = *pphead;while(cat->next!=NULL){cat = cat->next;}cat->next = newnode;}
}
void SListPushFront(SLTNode** pphead, SLTDataType x) {头插SLTNode* newnode = uuu(x);newnode->next = *pphead;*pphead = newnode;
}
void SListPopFront(SLTNode** pphead) {//头删SLTNode* next = (*pphead)->next;free(*pphead);*pphead = next;
}void SListPopBack(SLTNode** pphead) {//尾删if (*pphead == NULL)return;else if ((*pphead)->next == NULL) {free(*pphead);*pphead = NULL;}else {SLTNode* cat = *pphead;SLTNode* cat1= NULL;while (cat->next != NULL) {cat1 = cat;cat = cat->next;}free(cat);cat1->next = NULL;}
}

Test:

#define _CRT_SECURE_NO_WARNINGS
#include"SList.h"void  Test() {SLTNode* plist = NULL;SListPushBack(&plist, 1);SListPushBack(&plist, 2);SListPushFront(&plist, 0);SListPopFront(&plist);SListPopBack(&plist);SListPrint(plist);
}
int main() {Test();return 0;
}

还有查改等没写,有兴趣的可以去试试哦
以上就是我的分享了,如果有什么错误,欢迎在评论区留言。
最后,谢谢大家的观看!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

经典滑动窗口试题(二)

&#x1f4d8;北尘_&#xff1a;个人主页 &#x1f30e;个人专栏:《Linux操作系统》《经典算法试题 》《C》 《数据结构与算法》 ☀️走在路上&#xff0c;不忘来时的初心 文章目录 一、水果成篮1、题目讲解2、讲解算法思路3、代码实现 二、找到字符串中所有字母异位词1、题目…

合并区间[中等]

一、题目 以数组intervals表示若干个区间的集合&#xff0c;其中单个区间为intervals[i] [starti, endi]。请你合并所有重叠的区间&#xff0c;并返回一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间。 示例 1&#xff1a; 输入&#xff1a;intervals […

初探HarmonyOS路由跳转

最近的鸿蒙新闻也是很大声势&#xff0c;鸿蒙的纯血版一出&#xff0c;各大互联网大厂都坐不住了&#xff0c;纷纷加入其中。这意味鸿蒙将来会取代大部分Android用户&#xff0c;这也是程序员的一篇大好前程。如今的Android开发行业已经夕阳西下了。 网上有关HarmonyOS的资料几…

SVD recommendation systems

SVD recommendation systems 为什么在推荐系统中使用SVD 一个好的推荐系统一定有小的RMSE R M S E 1 m ∑ i 1 m ( Y i − f ( x i ) 2 RMSE \sqrt{\frac{1}{m} \sum_{i1}^m(Y_i-f(x_i)^2} RMSEm1​i1∑m​(Yi​−f(xi​)2 ​ 希望模型能够在已知的ratings上有好的结果的…

springboot整合redis+自定义注解+反射+aop实现分布式锁

1.定义注解 import java.lang.annotation.*; import java.util.concurrent.TimeUnit;/** Author: best_liu* Description:* Date: 16:13 2023/9/4* Param * return **/ Retention(RetentionPolicy.RUNTIME) Target({ElementType.METHOD}) Documented public interface RedisLo…

Ubuntu系统Springboot项目Nginx安装(编译安装方式)

1.下载 nginx官网下载 Index of /download/ 2.解压 这里我下载的1.25.3版本&#xff0c;系统是ubuntu 解压 tar -zxvf nginx-1.25.3.tar.gz 3.编译安装 安装前需要执行安装一些系统依赖 3.1安装PCRE库 ubuntu&#xff1a;执行以下命令 sudo apt-get install libpcre…

MOSFET安全工作区域SOA

Safe Operating Area&#xff08;SOA&#xff09;即安全工作区&#xff1a;描述了当MOSFET工作在饱和区时可以处理的最大功率。超出安全工作区&#xff0c;则可能导致元件损坏。 SOA分为五个单独的界限&#xff0c;分别是RDS(on)限制 On Resistance&#xff08;RDS(on)&#…

Kafka系列 - Kafka一篇入门

Kafka是一个分布式流式处理平台。很多分布式处理系统&#xff0c;例如Spark&#xff0c;Flink等都支持与Kafka集成。 Kafka使用场景 消息系统&#xff1a;Kafka实现了消息顺序性保证和回溯消费。存储系统&#xff1a;Kafka把消息持久化到磁盘&#xff0c;相比于其他基于内存的…

⑨【Stream】Redis流是什么?怎么用?: Stream [使用手册]

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ ⑨Redis Stream基本操作命令汇总 一、Redis流 …

苹果mac屏幕投屏镜像工具AirServer2024

airserver 是什么软件&#xff1f;AirServer 是一款 Airplay Mac屏幕镜像应用&#xff0c;AirServer可以通过 mac 实时接收iPhone、iPad以及Android设备的实时屏幕画面。AirServer 可以将一个简单的大屏幕或投影仪变成一个通用的屏幕镜像接收器。在您的大屏幕上启用 AirServer …

八股文面试day6

什么是代理&#xff1f;为什么要用动态代理&#xff1f; 代理模式大概意思是&#xff1a;为其他对象提供一个代理项或者是占位符&#xff0c;以控制对这个对象的访问 代理模式核心思想&#xff1a;创建一个代理对象&#xff0c;在客户端和目标对象之间的一个中介&#xff0c;…

MySQL与Redis如何保证数据的一致性

文章目录 MySQL与Redis如何保证数据的一致性&#xff1f;不好的方案1. 先写 MySQL&#xff0c;再写 Redis2. 先写 Redis&#xff0c;再写 MySQL3. 先删除 Redis&#xff0c;再写 MySQL 好的方案4. 先删除 Redis&#xff0c;再写 MySQL&#xff0c;再删除 Redis5. 先写 MySQL&am…

实现极坐标图表QPolarChart的角度轴范围是[0,360]时,0度在水平右侧

目录 参考角度轴范围是[0,360]时&#xff0c;0度在水平右侧.h.cpp 参考 Qt数据可视化(QPolarChart雷达图) 默认QPolarChart的范围是[0,360]时&#xff0c;0度在垂直上方 如官方例子QValueAxis角度轴范围是[-100,100] 角度轴范围是[0,360]时&#xff0c;0度在水平右侧 原理&am…

如何在GO中写出准确的基准测试

一般来说&#xff0c;我们不应该对性能进行猜测。在编写优化时&#xff0c;会有许多因素可能起作用&#xff0c;即使我们对结果有很强的看法&#xff0c;测试它们很少是一个坏主意。然而&#xff0c;编写基准测试并不简单。很容易编写不准确的基准测试&#xff0c;并且基于这些…

C语言进阶之笔试题详解(1)

引言&#xff1a; 对指针知识进行简单的回顾&#xff0c;然后再完成笔试题。 ✨ 猪巴戒&#xff1a;个人主页✨ 所属专栏&#xff1a;《C语言进阶》 &#x1f388;跟着猪巴戒&#xff0c;一起学习C语言&#x1f388; 目录 引言&#xff1a; 知识简单回顾 指针是什么 指针变…

vue项目中使用jsonp跨域请求百度联想接口

一. 内容简介 vue项目中使用jsonp跨域请求百度联想接口 二. 软件环境 2.1 Visual Studio Code 1.75.0 2.2 chrome浏览器 2.3 node v18.14.0 三.主要流程 3.1 代码 核心代码 // 这个是请求函数doLeno() {// 挂载回调函数&#xff0c;不挂载&#xff0c;会报不存在window…

React入门使用 (官方文档向 Part1)

文章目录 React组件:万物皆组件 JSX: 将标签引入 JavaScriptJSX 规则1. 只能返回一个根元素2. 标签必须闭合3. 使用驼峰式命名法给 ~~所有~~ 大部分属性命名&#xff01;高级提示&#xff1a;使用 JSX 转化器 在 JSX 中通过大括号使用 JavaScript使用引号传递字符串使用大括号&…

性能优化中使用Profiler进行内存泄露的排查及解决方式

文章目录 一、前言二、内存泄露的排查方式三、参考链接 一、前言 对于常规意义上的线程使用要及时关闭&#xff0c;数据库用完要及时关闭&#xff0c;数据用完要及时清空等等这里不再赘述&#xff0c;但是在开发中总会有不熟悉的api&#xff0c;开发进度过快&#xff0c;开发人…

【工具】Zotero|使用Zotero向Word中插入引用文献(2023年)

版本&#xff1a;Word 2021&#xff0c;Zotero 6.0.30 前言&#xff1a;两年前我找网上插入文献的方式&#xff0c;网上的博客提示让我去官网下个插件然后才能装&#xff0c;非常麻烦&#xff0c;导致我对Zotero都产生了阴影。最近误打误撞发现Zotero自带了Word插件&#xff0c…

随时随地,打开浏览器即可体验的在线PS编辑器

即时设计 即时设计是国产的专业级 UI 设计工具&#xff0c;不限平台不限系统&#xff0c;在浏览器打开即用&#xff0c;能够具备 Photoshop 的设计功能&#xff0c;钢笔、矢量编辑、矩形工具、布尔运算等设计工具一应俱全&#xff0c;是能够在线使用的 Photoshop 免费永久工具…