【数据结构初阶】手撕单链表

news/2024/12/2 16:43:37/

目录

  • 一.链表概念和结构
    • 二.单链表功能的实现
      • 1.打印单链表内容
      • 2.申请单链表节点
      • 3.头插和尾插
      • 4.头删和尾删
      • 5.单链表查找
      • 6.pos位置前后插入
      • 7.pos位置删除
      • 三.链表面试题剖析

一.链表概念和结构

概念:链表是一种物理存储结构连续、顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。
正像概念所说的,链表并不像顺序表那样在物理存储结构式是连续、顺序的。而是在逻辑上是连续的。

结构如下图所示:
在这里插入图片描述
创建一个结构体,存放一个数据元素和一个指向下一个结构体的指针,最后一个指针为NULL,这就构成了单链表;

typedef int SLDataType;typedef struct SListNode
{SLDataType data;//存放数据元素struct SListNode* next;//指向下一个结构体的指针
}SLTNode;SLTNode* P=NULL;//初始化单链表

二.单链表功能的实现

1.打印单链表内容

我们使用单链表存储数据后,为了方便我们检查数据是否正常存储,应该设计函数来打印当前单链表的内容。并且函数接受的结构体指针不需要断言检查,因为就算单链表为空也应当像顺序表那样打印出来

void SLTPintf(SLTNode* phead)
{SLTNode* cur = phead;while (cur != NULL){printf("%d->", cur->data);cur = cur->next;}printf("NULL\n");
}

2.申请单链表节点

再后来我们要对链表进行插入时,就必须要再申请新的链表节点进行插入,所以我们可以分装申请节点的函数,在插入操作前调用此函数即可。

SLTNode* AppSLTnext(SLDataType x)
{SLTNode* nextnode = (SLTNode*)malloc(sizeof(SLTNode));if (nextnode == NULL){perror("malloc fail");return NULL;}nextnode->data = x;nextnode->next = NULL;return nextnode;
}

3.头插和尾插

像插入和删除的操作都是会对链表进行修改的所以函数参数需要使用二级指针来接受。
头插比较简单,如下操作即可:

void SLTPushFront(SLTNode** pphead, SLDataType x)
{SLTNode* nextnode = AppSLTnext(x);nextnode->next = *pphead;*pphead = nextnode;
}

尾插则要区分链表是否为空,以及要进行找尾的重要操作

void SLTPushBack(SLTNode** pphead, SLDataType x)
{SLTNode* nextnode = AppSLTnext(x);if (NULL == *pphead){*pphead = nextnode;}else{SLTNode* tail = *pphead;while (tail->next != NULL)//找尾{tail = tail->next;}tail->next = nextnode;}
}

4.头删和尾删

删除操作则需要对指针的内容进行检查,因为如果链表为空则不能够进行删除的操作。
头删操作如下:

void SLTPopFront(SLTNode** pphead)
{assert(*pphead);SLTNode* first = *pphead;*pphead = first->next;free(first);first = NULL;
}

尾删的找尾与尾插的找尾则稍有不同:

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

5.单链表查找

SLTNode* SLTFind(SLTNode* phead, SLDataType x)
{//不直接使用传过来的指针,优雅永不过时SLTNode* cur = phead;//第一种while (cur->data != x){cur = cur->next;}return cur;//第二种/*while (cur){if (cur->data == x)return cur;cur = cur->next;}return NULL;*/
}

6.pos位置前后插入

前插需要考虑指针是否为空的情况,还有如果pos就在第一位,则等同于头插操作。

void SLTInsert(SLTNode** pphead, SLTNode* pos, SLDataType x)
{assert(pphead);assert(pos);if (pos = *pphead)SLTPushFront(pphead, x);else{SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}SLTNode* newnode = AppSLTnext(x);newnode->next = prev->next;prev->next = newnode;}
}

尾插相较简单些:

void SLTInsertAfter(SLTNode* pos, SLDataType x)
{SLTNode* newnode = AppSLTnext(x);newnode->next = pos->next;pos->next = newnode;
}

7.pos位置删除

pos位置删除:

void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead);assert(*pphead);if (pos = *pphead)SLTPopFront(pphead);else{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);assert(pos->next);SLTNode* cur = pos->next;pos->next = cur->next;free(cur);cur = NULL;
}

单链表的功能实现到此为止,感谢你们的阅读!

三.链表面试题剖析

欲知后事如何,且听下回分解。我将在下一篇博客详解多道面试题。


http://www.ppmy.cn/news/29910.html

相关文章

GEE开发之降雨(CHIRPS)数据获取和分析

GEE开发之降雨CHIRPS数据获取和分析1.数据介绍2.初识CHIRPS2.1 代码一2.2 代码二3.逐日数据分析和获取4.逐月数据分析和获取4.1 代码一4.2 代码二(简洁)5.逐年数据分析和获取5.1 代码一5.2 代码二(简洁)前言:主要获取和分析UCSB-CHG/CHIRPS/DAILY的日数据、月数据和…

Elasticsearch的搜索命令

Elasticsearch的搜索命令 文章目录Elasticsearch的搜索命令数据准备URI Searchq(查询字符串)analyzer(指定查询字符串时使用的分析器)df(指定查询字段)_source(指定返回文档的字段)s…

第十四届蓝桥杯三月真题刷题训练——第 1 天

目录 题目1:数列求值 代码: 题目2:质数 代码: 题目3:饮料换购 代码: 题目1:数列求值 题目描述 本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出…

4. 字符设备驱动高级--- 下篇

文章目录一、字符设备驱动高级1.1 注册字符设备驱动新接口1.1.1 新接口与旧接口1.1.2 cdev介绍1.1.3 设备号1.1.4 编程实践1.1.5 alloc_chrdev_region自动分配设备号1.1.6 中途出错的倒影式错误处理方法二、字符设备驱动注册代码分析2.1 旧接口register_chrdev2.2 新接口regist…

Docker学习(十七)save 和 export 命令的区别

Docker 中有两个命令可以将镜像导出为本地文件系统中的 tar 文件:docker save 和 docker export。尽管它们的作用类似,但它们之间有一个重要的区别。 1.使用方式的不同: docker save 的使用示例: docker save -o test.tar image…

【C++】内存管理

C/C内存分布C语言中动态内存管理方式C内存管理方式new/delete操作内置类型new和delete操作自定义类型operator new与operator delete函数new和delete的实现原理定位new表达式(placement-new)C/C内存分布 在C/C中关于内存的知识是非常重要的,只有清楚的了解内存的相…

将微信小程序页面转为图片

最近做项目遇到一个需求,那就是要将某个页面转为图片然后传给后端,我仔细找了一圈,发现官方那个Api也就是wx.canvasToTempFilePath生成的图片很有可能为空,太坑了,于是我放弃用它了,选择了用wxml2canvas。 安装wxml2canvas npm init npm install wxml2canvas --save --…

MDK软件使用技巧

本文主要汇总MDK软件使用技巧 一、字体大小及颜色修改 第一步点击工具栏的这个小扳手图标 进去后显示如下,先设置 Encoding 为:Chinese GB2312(Simplified),然后设置 Tab size 为:4 以更好的支持简体中文,否则&…