数据结构-单链表

文章目录

    • 单链表概念
    • 链接存储方法
    • 头指针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.mzph.cn/news/179725.shtml

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

相关文章

MYSQL 8.X Linux-Generic 通用版本安装

下载对应版本MySQL :: Download MySQL Community Server (Archived Versions) 这里我选择的是Linux - Generic (glibc 2.12) (x86, 64-bit), TAR 解压到服务器 只需要里面的mysql-8.0.24-linux-glibc2.12-x86_64.tar.xz 在目录下创建需要的文件夹 这里我改名为mysql-8.0.24…

GitLab 登录中,LDAP和 Standard 验证有什么区别

在 GitLab 中&#xff0c;LDAP&#xff08;Lightweight Directory Access Protocol&#xff09;和 Standard 验证是两种不同的身份验证方法&#xff0c;它们有以下区别&#xff1a; LDAP&#xff08;Lightweight Directory Access Protocol&#xff09;身份验证&#xff1a; L…

西南科技大学(数据结构A)期末自测练习二

一、填空题(每空1分,共10分) 1、在线性表的下列运算中,不改变数据元素之间结构关系的运算是( D ) A、插入 B、删除 C、排序 D、定位 2、顺序表中第一个元素的存储地址是100,每个元素的长度为2,则第5个元素的地址是( B ) A.110 B.108 C.100 …

C#中的async/await异步编程模型

前言 当谈到异步编程时&#xff0c;C#中的async/await是一个强大且方便的工具。它使得编写并发和异步操作变得更加简单和可读&#xff0c;同时提供良好的可维护性。本文将详细解释async/await的使用&#xff0c;以及如何在C#中有效地利用它来实现异步操作。 目录 前言1. async…

在线教育机构如何借助小程序技术创新

随着人工智能AI技术的发展&#xff0c;我们的生活学习工作方式都在经历变化。在线教育也处于这场变化的核心之中&#xff0c;同样借助这股东风引来了行业的一波红利期。 在正式分享在线教育行业的开始&#xff0c;我们先简单搞清楚什么是在线教育。 在线教育行业是指通过互联…

PCF8591多通道数据读取异常问题

问题描述 PCF8591在循环读取两个通道时&#xff0c;两个通道数据出现交错问题。 例如我们想实现&#xff1a;第一次读取通道一、第二次读取通道二、第三次读取通道一、第四次读取通道二……依次循环 但实际数据&#xff1a;第一次读取的值为0x80、第二次读取的值为通道一的值、…

2023.11.28-电商平台建设03 - 大数据调优手段

1.优化手段 1.1分桶表 HIVE的分桶本质上就是MR的分区操作 建表语句: create table 表名(字段 类型,.... ) clustered by(分桶字段) [sorted by (字段 [asc | desc])] into N buckets --- 定义分桶表核心语句 row format...... 分桶的作用 1) 进行数据采样工作 1.1) …

final关键字-Java

final关键字 一、使用场景1、当不希望类被继承时&#xff0c;可以用final修饰。2、当不希望父类的某个方法被子类覆盖/重写(override)时&#xff0c;可以用final修饰。3、当不希望类的的某个属性的值被修改&#xff0c;可以用final修饰。4、当不希望某个局部变量被修改&#xf…

智能优化算法应用:基于花授粉算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于花授粉算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于花授粉算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.花授粉算法4.实验参数设定5.算法结果6.参考文献7.…

好用的json处理工具He3 JSON

官网地址&#xff1a;https://he3app.com/zh/ json格式化 https://portal.he3app.com/home/extension/json-to-pretty 其他 https://portal.he3app.com/home/category

芯能科技-603105 三季报分析(20231123)

芯能科技-603105 基本情况 公司名称&#xff1a;浙江芯能光伏科技股份有限公司 A股简称&#xff1a;芯能科技 成立日期&#xff1a;2008-07-09 上市日期&#xff1a;2018-07-09 所属行业&#xff1a;电气机械和器材制造业 周期性&#xff1a;1 主营业务&#xff1a;分布式光伏解…

每日一练:简易计算器

1. 题目 设计实现一个简易的计算器&#xff0c;可以进行加减乘除的计算。可以考虑通过GUI和命令行输入等方式实现。 2. 设计思路 创建一个简单的用户界面&#xff0c;可以使用 Python 的 Tkinter模块。在界面上放置按钮&#xff0c;每个按钮代表一个数字、运算符或其他功能。…

家政预约服务管理系统,轻松搭建专属家政小程序

家政预约服务管理系统&#xff0c;轻松搭建专属家政小程序app&#xff1b; 家政服务app开发架构包括&#xff1a; 1. 后台管理端&#xff1a;全面管理家政服务、门店、员工、阿姨信息、订单及优惠促销等数据&#xff0c;并进行统计分析。 2. 门店端&#xff1a;助力各门店及员工…

Linux命令中的符号

目录 1 管道符 | 1.1 | grep [要检索的东西] 1.2 echo | tee 2 重定向 2.1 输出重定向覆盖 > 2.2 输出重定向添加 >> 2.3 文件输入重定向 < 2.4 多行文本输入重定向 << 2.5 常用搭配 2.5.1 终端不显示 > /dev/null 1 管道符 | 我们…

使用.NET8中的.http文件和终结点资源管理器

本文将以.NET8的模板增加的.http文件为引&#xff0c;介绍 Visual Studio 2022 中的 .http 文件编辑器&#xff0c;这是一个用于测试 ASP.NET Core 项目的强大工具。 文章目录 1. 背景2. HTTP 文件介绍2.1 简介2.2 .http 文件语法3. 在 Visual Studio 中使用3.1 终结点资源管理…

基于Spring原生框架构建原生Spring的第一个程序!

&#x1f609;&#x1f609; 学习交流群&#xff1a; ✅✅1&#xff1a;这是孙哥suns给大家的福利&#xff01; ✨✨2&#xff1a;我们免费分享Netty、Dubbo、k8s、Mybatis、Spring...应用和源码级别的视频资料 &#x1f96d;&#x1f96d;3&#xff1a;QQ群&#xff1a;583783…

04_Flutter自定义Slider滑块

04_Flutter自定义Slider滑块 一.Slider控件基本用法 Column(mainAxisAlignment: MainAxisAlignment.start,children: <Widget>[Text("sliderValue: ${_sliderValue.toInt()}"),Slider(value: _sliderValue,min: 0,max: 100,divisions: 10,thumbColor: Colors.…

Nacos2.x配置中心源码分析

概述 源码注释参考 git 仓库&#xff0c;对应流程图后续补充&#xff1b; 启动 nacos nacos 启动类&#xff1a; // com.alibaba.nacos.NacosSpringBootApplication(scanBasePackages "com.alibaba.nacos") ServletComponentScan EnableScheduling public class…

MySQL事务(简单明了)

目录 1. 事务的特性&#xff08;ACID&#xff09;&#xff1a; 2. 事务的语法&#xff1a; 3. 隔离级别&#xff1a; 4. 保存点&#xff08;Savepoints&#xff09;&#xff1a; 5. 示例&#xff1a; 1. 事务的特性&#xff08;ACID&#xff09;&#xff1a; 原子性&#…

WebUI自动化学习(Selenium+Python+Pytest框架)003

1.元素操作 在成功定位到元素之后&#xff0c;我们需要对元素进行一些操作动作。常用的元素操作动作有&#xff1a; &#xff08;1&#xff09;send_keys() 键盘动作&#xff1a;向浏览器发送一个内容&#xff0c;通常用于输入框输入内容或向浏览器发送快捷键 &#xff08;2…