【数据结构】单链表 | 详细讲解

线性表顺序存储结构的优缺点

顺序表优点

  • 无须为了表示中间的元素之间的逻辑关系而增加额外的存储空间;
  • 因为以数组形式存储,可以快速地存取表中任一位置的元素。

顺序表缺点

  • 插入和删除操作需要移动大量元素,时间复杂度为O(N);
  • 当线性表长度变化较大时,难以确定存储空间的容量;
  • 造成存储空间的“碎片”。

顺序存储结构不足的解决办法

其实顺序表最大的缺点就是插入和删除时需要移动大量元素,这显然就需要耗费极大时间,因为相邻两元素的存储位置也具有邻居关系。它们编号是1,2,3,...,n,它们在内存中的位置也是挨着的,中间没有空隙,当然就无法快速介入,而删除后,当中就会留出空隙,自然需要弥补。

那这样的话,我们反正都要让相邻的元素都留有足够余地,那么干脆所有的元素都不考虑相邻位置了,哪里有空位就到哪里,而只是让每个元素知道他下一个元素的位置在哪里,这样我们就可以在第一个元素时,就知道第二个元素的位置(内存地址),而找到它;在第二个元素时,就知道第三个元素的位置(内存地址),而找到它。这样所有的元素我们就都可以通过遍历而找到了。

其实这个思路也就是链表存储思路,而本篇文章着重讲述链表中的单链表。

线性表链式存储结构定义

在链式结构中,除了要存储数据元素信息外,还要存储它的后继元素的存储地址。

数据域:存储数据元素信息的域称为数据域;

指针域:存储直接后继位置的域称为指针域。

在指针域中存储的信息称为指针或链。数据域与指针域信息组成数据元素的存储映像,称为结点。

单链表:n个结点链结成的链表,此链表中的每个结点中只包含一个指针域。

单链表的代码实现以及分析 

单链表的结构代码

单链表中的结点,是由存放数据元素的数据域和存放后继结点地址的指针域组成的。所以,假设这个数据为val,存放后继结点地址的指针为next。

typedef int SLNDataType;
typedef struct SListNode
{struct SListNode* next;SLNDataType val;
}SLNode;

单链表中的每一个节点都是一个结构体成员,也就是多个结构体构成了一条链表。这与顺序表不同,顺序表由于数组存储 ,所以就是一个结构体的数组中存储了多个节点。

单链表的遍历打印

void SLTPrint(SLNode* phead)
{assert(phead);SLNode* cur = phead;while (cur != NULL){printf("%d->", cur->val);cur = cur->next;}printf("NULL\n");
}

单链表建立新的头结点 

在创建新的头结点时,需要用到malloc函数,关于malloc的使用方法,这里不做过多阐述,大家有什么不懂的,可以点击链接(单击即可查看)详细学习malloc的使用方法哦。

C库函数中 void *malloc(size_t size) 分配所需的内存空间,并返回一个指向它的指针。

malloc分配内存空间函数。

 

SLNode* SLTCreateNode(SLNDataType x)
{SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));if (newnode == NULL){perror("malloc fail\n");exit(-1);}newnode->next = NULL;newnode->val = x;return newnode;
}

单链表的尾插

那如果这是一个空表的话,那么就直接让这个单链表为指针,指向新创建的节点。

 

void SLTPushBack(SLNode** pphead, SLNDataType x)
{assert(pphead);SLNode* Newnode = SLTCreateNode(x);if (*pphead == NULL){*pphead = Newnode;}else{SLNode* tail = pphead;while (tail->next != NULL){tail = tail->next;}tail->next = Newnode;}
}

单链表的头插

 

void SLTPushFront(SLNode** pphead, SLNDataType x)
{assert(pphead);SLNode* Newnode = SLTCreateNode(x);Newnode->next = *pphead;*pphead = Newnode;
}

单链表的尾删

 

void SLTPopBack(SLNode** pphead)
{assert(pphead);assert(*pphead);if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}else{SLNode* tail = *pphead;while (tail->next->next != NULL){tail = tail->next;}free(tail->next);tail->next = NULL;}
}

单链表的头删

 

 

void SLTPopFront(SLNode** pphead)
{assert(pphead);assert(*pphead);SLNode* cur = (*pphead)->next;//注意在单链表头删的时候,如果只有一个节点,那也是可以的,就让那个临时的为空free(*pphead);*pphead = cur;
}

单链表的查找x数据

 

SLNode* SLTFind(SLNode* phead, SLNDataType x)
{SLNode* cur = phead;while (cur){if (cur->val == x){return cur;}else{cur = cur->next;}}return NULL;
}

单链表在pos位置插入x的数

 

SLNode* SLTInsert(SLNode** pphead, SLNode* pos, SLNDataType x)
{assert(*pphead);assert(pphead);assert(pos);if (*pphead==pos){SLTPushFront(pphead,x);}else{SLNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}SLNode* Newnode = SLTCreateNode(x);prev->next = Newnode;Newnode->next = pos;}
}

单链表删除pos位置上的值

void SLTErase(SLNode** pphead, SLNode* pos)
{assert(*pphead);assert(pphead);assert(pos);if (pos == *pphead){SLTPopFront(pphead);}else{SLNode* prev = *pphead;while (prev->next!=pos){prev = prev->next;}prev->next = pos->next;free(pos);pos = NULL;}
}

单链表的销毁

void SLTDestroy(SLNode** pphead)
{assert(pphead);SLNode* cur = *pphead;while (cur){SLNode* tmp = cur->next;free(cur);cur = tmp;}*pphead = NULL;
}

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

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

相关文章

Android图形系统之X11、Weston、Wayland、Mesa3D、ANGLE、SwiftShader介绍(十五)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…

redis运维(七)基础通用命令

一 基础通用命令 备注: 与具体数据类型无关Tab键 自动补全补充: redis 命令是不区分大小写 通用不到 10 个提升逼格的 redis 命令 后续: slowlog、rename-command、monitor、set ① help command 需求: 显示有关redis命令的…

就近值 reduce用法 时间戳与时间点对比循环查找

后台接口返回的13为时间戳 需要与数据data的time做对比,查找出最近的值 data的数据结构如下: 将:改为空格,变成数字之间的对比 //查找最近的时间getNearestTime(timestamp, data) {let date new Date(timestamp)let h date.ge…

openGauss学习笔记-122 openGauss 数据库管理-设置密态等值查询-密态支持函数/存储过程

文章目录 openGauss学习笔记-122 openGauss 数据库管理-设置密态等值查询-密态支持函数/存储过程122.1 创建并执行涉及加密列的函数/存储过程 openGauss学习笔记-122 openGauss 数据库管理-设置密态等值查询-密态支持函数/存储过程 密态支持函数/存储过程当前版本只支持sql和P…

postgreSQL中的高速缓存

1. 高速缓存简介 ​如下图所示,当一个postgreSQL进程读取一个元组时,需要获取表的基本信息(例如:表的oid、索引信息和统计信息等)及元组的模式信息,这些信息被分别记录在多个系统表中。通常一个表的模式信…

报错资源不足,k8s使用containerd运行容器修改挂载点根目录换成/home

运行k8s一段时间发现存储不足报错 发现这里用的是根路径的挂载,修改一下

手撕无头单链表

💓 博客主页:江池俊的博客⏩ 收录专栏:数据结构探索👉专栏推荐:✅C语言初阶之路 ✅C语言进阶之路💻代码仓库:江池俊的代码仓库🔥编译环境:Visual Studio 2022&#x1f38…

【Python】jupyter notebook(学习笔记)

Jupyter Notebook初见 1、Jupyter Notebook介绍 web版的ipython 编程、写文档、记笔记、展示 格式.ipynb 2、为什么使用Jupyter Notebook? 画图方面的优势:图像的生成不会堵塞后面代码的执行数据展示方面的优势:生成的数据可以保存在文件中 3、J…

hive数仓-数据的质量管理

版本20231116 要理解数据的质量管理,应具备hive数据仓库的相关知识 文章目录 1.理解什么是数据的质量管理:2.数据质量管理的规划数据质量标准的分类 3.数据质量管理解决方案1.ods层的数据质量校验1)首先在hive上建立一个仓库,添加…

oracle初步学习

先了解几个登录的方式 1.直接在cmd输入 sqlplus scott/tiger //登陆普通用户scott 2.输入sqlplus sys as sysdba 之后 紧接着让你输入口令,直接输入sys就行了 3.先输入sqlplus/nolog 在输入conn system/managerorcl 先在cmd窗口输入sqlplus/nolog &#x…

Linux输入设备应用编程(键盘,触摸屏,按键,鼠标)

目录 一 输入设备编程介绍 1.1 什么是输入设备呢? 1.2 什么是输入设备的应用编程? 1.3 input子系统 1.4 数据读取流程 1.5 应用程序如何解析数据 1.5.1 按键类事件: 1.5.2 相对位移事件 1.5.3 绝对位移事件 二 读取 struct input_e…

Swift爬虫程序

以下是一个简单的Swift爬虫程序,用于从前程无忧深圳地区招聘财务、会计的数据爬取数据: import Foundation import SwiftSoup// 创建一个请求对象,指定代理信息 var request URLRequest(url: URL(string: "https://www.51job.com/zh/c…

【软件安装】Centos系统中安装docker容器(华为云HECS云耀服务器)

这篇文章,主要介绍Centos系统中安装docker容器(华为云HECS云耀服务器)。 目录 一、安装docker 1.1、卸载旧版本docker 1.2、更新repo镜像 1.3、安装依赖包 1.4、添加docker-ce镜像 1.5、安装docker-ce 1.6、查看docker安装版本 1.7、…

Maven介绍及仓库配置

目录 一.Maven 1.介绍 坐标 仓库 1)中央仓库 2)本地仓库 3)私服 配置国内源 配置过程 二.Maven功能 2.项目构建 3.依赖管理 Maven Help插件 安装 ​使用 一.Maven 1.介绍 坐标 唯一的,通过以下代码的三个键值对确…

【AI视野·今日CV 计算机视觉论文速览 第277期】Fri, 27 Oct 2023

AI视野今日CS.CV 计算机视觉论文速览 Fri, 27 Oct 2023 Totally 93 papers 👉上期速览✈更多精彩请移步主页 Daily Computer Vision Papers A Coarse-to-Fine Pseudo-Labeling (C2FPL) Framework for Unsupervised Video Anomaly Detection Authors Anas Al lahham…

Spring-IoC与DI入门案例

IoC入门案例 IoC入门案例思路分析 管理什么?(Service与Dao)如何将被管理的对象告知IoC容器?(配置)被管理的对象交给IoC容器,如何获取到IoC容器?(接口)IoC容…

tcpdump wireshark简单使用

tcpdump工作原理 tcpdump 是 Linux 系统中非常有用的网络工具,运行在用户态,本质上是通过调用 libpcap 库的各种 api 来实现数据包的抓取功能,利用内核中的 AF_PACKET 套接字,抓取网络接口中传输的网络包。查 看 tcpdump 的 手册…

JVM实战-JVM之类加载时机

目录 JVM实战-JVM之类加载时机1 主动引用2 被动引用 JVM实战-JVM之类加载时机 Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验、转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这个过程被称作虚拟机的类加载机…

JS 读取excel文件内容 和 将json数据导出excel文件

一、实现将json数据导出为excel文件 1、通过原生js实现 核心方法: function JSONToExcelConvertor(JSONData, FileName, title, filter) {if (!JSONData)return;//转化json为objectvar arrData typeof JSONData ! object ? JSON.parse(JSONData) : JSONData;va…