当前位置: 首页 > news >正文

【数据结构】单链表详解

前言

为了解决顺序表存在的一些问题,我们引入了单链表~

欢迎关注个人主页:逸狼


创造不易,可以点点赞吗~

如有错误,欢迎指出~


目录

前言

顺序表存在一定的问题

与顺序表的对比

认识链表

链表结构

打印节点

头文件SList.h

源文件SList.c

源文件test.c

尾插和头插

源文件SList.c

运行结果​编辑

头删和尾删

源文件SList.c

运行结果

查找

源文件SList.c

运行结果

在指定位置之前和之后插入数据

源文件SList.c

运行结果

删除指定位置和其之后的数据

源文件SList.c

运行结果


顺序表存在一定的问题

  1. 顺序表的中间/头部的插入、删除需要挪动数据
  2. 扩容存在性能的消耗
  3. 会有空间的浪费

而链表可以规避这些问题~

与顺序表的对比

认识链表

链表是⼀种物理存储结构上⾮连续、⾮顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

  • 链表由一个个节点组成
  • 每个节点的组成:当前节点要保存的数据 和 保存下⼀个节点的地址(指针变量)。
  • 通过指针变量来保存下⼀个节点位置才能从当前节点找到下⼀个节点。
  • 可以增加或减少节点

链表结构

typedef int SLTDataTpye;//链表由节点组成
typedef struct SListNode
{SLTDataTpye data;//存储当前节点的数据SLTNode* next;//存储下一节点的地址
}SLTNode;//将该链表命名为SLTNode//typedef struct SListNode SLTNode;

打印节点

头文件SList.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<assert.h>typedef int SLTData;
typedef struct SListNode SLTNode;//定义节点
struct SListNode {SLTData data;struct SListNode* next;
};//打印链表
void SLTPrint(SLTNode* phead);//销毁链表
void SLTDesTroy(SLTNode** pphead);

源文件SList.c

#include"SList.h"//打印链表
void SLTPrint(SLTNode* phead)
{//用pcur遍历链表SLTNode* pcur = phead;while (pcur){printf("%d->", pcur->data);pcur = pcur->next;}printf("NULL\n");
}//销毁链表
void SLTDesTroy(SLTNode** pphead)
{assert(pphead);assert(*pphead);SLTNode* pcur = *pphead;//循环删除节点while (pcur){SLTNode* next = pcur->next;//创建next节点保存pcur下一个节点free(pcur);pcur = next;}*pphead = NULL;
}

源文件test.c

#include"SList.h"void SListTest01()
{//对第一个节点申请了空间SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));node1->data = 1;SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));node2->data = 2;SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));node3->data = 3;SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));node4->data = 4;//将节点连接在一起node1->next = node2;node2->next = node3;node3->next = node4;node4->next = NULL;//创建链表plistSLTNode* plist = node1;//plist指针保存了第一个节点的地址SLTPrint(plist);
}int main()
{SListTest01();return 0;
}

尾插和头插

尾插

头插

指针关系

源文件SList.c

//申请一个新节点的方法
SLTNode* SLTBuyNode(SLTDataType x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));newnode->data = x;newnode->next = NULL;return newnode;
}//链表的头插和尾插
//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x)//链表头节点的地址和要插入的数据
{//排查空指针assert(pphead);SLTNode* newnode = SLTBuyNode(x);//链表为空,新节点作为pheadif (*pphead == NULL){*pphead = newnode;return;}//链表不为空,找尾节点SLTNode* ptail = *pphead;while (ptail->next){ptail = ptail->next;}//此时ptail就是尾节点ptail->next = newnode;
}
//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{assert(pphead);SLTNode* newnode = SLTBuyNode(x);newnode->next = *pphead;*pphead = newnode;
}

运行结果

头删和尾删

源文件SList.c

//链表的头删和尾删
//尾删
void SLTPopBack(SLTNode** pphead)
{assert(pphead);//链表不能为空assert(*pphead);//只有一个节点if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;return;}//有多个节点SLTNode* ptail = *pphead;SLTNode* prev = NULL;//让ptail走到尾节点while (ptail->next){prev = ptail;ptail = ptail->next;}//销毁尾节点prev->next = NULL;free(ptail);ptail = NULL;
}//头删
void SLTPopFront(SLTNode** pphead)
{assert(pphead);//链表不能为空assert(*pphead);//让第二个节点成为新的头SLTNode* next = (*pphead)->next;//把旧节点释放掉free(*pphead);*pphead = next;
}

运行结果

查找

源文件SList.c

//查找
SLTNode* SLTFind(SLTNode** pphead, SLTDataType x)
{assert(pphead);//遍历链表SLTNode* pcur = *pphead;while (pcur){if (pcur->data == x){return pcur;}pcur = pcur->next;}//没有找到return NULL;
}

运行结果

在指定位置之前和之后插入数据

指定位置之前

指定位置之后

源文件SList.c

//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pphead);assert(pos);//要加上链表不能为空assert(*pphead);SLTNode* newnode = SLTBuyNode(x);//pos刚好是头节点if (pos == *pphead){//执行头插操作SLTPushFront(pphead, x);return;}//pos不是头节点的情况SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}//将prev newnode pos 3者连接起来prev->next = newnode;newnode->next = pos;}//在指定位置之后插入数据
void SLTInsertAfert(SLTNode* pos, SLTDataType x)
{assert(pos);SLTNode* newnode = SLTBuyNode(x);newnode->next = pos->next;pos->next = newnode;
}

运行结果

删除指定位置和其之后的数据

删除指定位置数据

删除指定位置之后

源文件SList.c

//删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead);assert(*pphead);assert(pos);//pos刚好是头节点时,没有前驱节点,执行头删if (*pphead == pos){//头删SLTPopFront(pphead);return;}//头节点没有前驱节点,所以要排除以上情况SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}prev->next = pos->next;free(pos);pos = NULL;
}//删除pos之后的节点
void SLTEraseAfter(SLTNode* pos)
{assert(pos);//pos->next是最后一个节点assert(pos->next);//先pos指向pos->next->next//再将pos->next释放//其中要先保存要删除的节点SLTNode* del = pos->next;pos->next = pos->next->next;free(del);del = NULL;
}

运行结果

相关文章:

  • 【C语言】—— 指针三 : 参透数组传参的本质
  • 记录一下在Pycharm中虚拟环境的创建
  • Spring Cloud Alibab 入门搭建,包含Nacos中心,注册服务发现服务,Feign请求,GateWay网关,sentinel限流
  • 2024/03/19(网络编程·day5)
  • 推免保研夏令营/预推免面试记录—北大软微
  • Linux基础开发工具之yum与vim
  • 【Jenkins】data stream error|Error cloning remote repo ‘origin‘ 错误解决【亲测有效】
  • K8s 集群高可用master节点ETCD挂掉如何恢复?
  • 学习vue3第五节(reactive 及其相关)
  • 计算机原理
  • 面试官:你说说Kafka是怎么保证消息可靠性的
  • 网络原理(3)——TCP协议
  • vue 中 清除form 校验状态
  • 关于继承是怎么样的?那当然是很好理解之
  • 解决Linux中Eclipse启动时找不到Java环境的问题
  • 《Javascript高级程序设计 (第三版)》第五章 引用类型
  • 【译】理解JavaScript:new 关键字
  • 【跃迁之路】【585天】程序员高效学习方法论探索系列(实验阶段342-2018.09.13)...
  • 03Go 类型总结
  • canvas 高仿 Apple Watch 表盘
  • Consul Config 使用Git做版本控制的实现
  • Django 博客开发教程 8 - 博客文章详情页
  • ES6之路之模块详解
  • exif信息对照
  • JSDuck 与 AngularJS 融合技巧
  • Linux下的乱码问题
  • php的插入排序,通过双层for循环
  • Spring Security中异常上抛机制及对于转型处理的一些感悟
  • Sublime text 3 3103 注册码
  • vue+element后台管理系统,从后端获取路由表,并正常渲染
  • 创建一个Struts2项目maven 方式
  • 基于Vue2全家桶的移动端AppDEMO实现
  • 近期前端发展计划
  • 看完九篇字体系列的文章,你还觉得我是在说字体?
  • 前端_面试
  • 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
  • 因为阿里,他们成了“杭漂”
  • 用element的upload组件实现多图片上传和压缩
  • 正则学习笔记
  • 白色的风信子
  • 7行Python代码的人脸识别
  • 关于Android全面屏虚拟导航栏的适配总结
  • # 透过事物看本质的能力怎么培养?
  • #Lua:Lua调用C++生成的DLL库
  • $.ajax()方法详解
  • ${factoryList }后面有空格不影响
  • $forceUpdate()函数
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (NSDate) 时间 (time )比较
  • (二)linux使用docker容器运行mysql
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (附源码)springboot青少年公共卫生教育平台 毕业设计 643214
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (附源码)计算机毕业设计SSM教师教学质量评价系统
  • (牛客腾讯思维编程题)编码编码分组打印下标(java 版本+ C版本)