数据结构–单链表

学习了顺序表,我们发现顺序表在向里面存放数据的时候很麻烦,比如我们要使用头插法存放一个数据到顺序表的时候,我们要将整个表都向后挪一位,这个操作就让人很难受。那么有没有一种结构可以让我们存放数据的操作变得简单一些呢?这就要用到线性结构的另一种–链表

链表的概念及结构

链表是一种物理存储结构上非连续、非顺序的的存储结构,数据元素的国际顺序是通过链表中的指针链接次序实现的。如下图:

注意:

  • 从上图可以看出,链式结构在逻辑上是连续的,但是在物理上不一定连续
  • 现实中的结点一般都是从堆上申请出来的
  • 从对上申请的空间,是按照一定的策略来分配的,两次申请的空间可能连续,也可能不连续

链表的分类

实际中链表的结构非常多,单链表、双向链表、带头单链表、带头双向链表、循环链表、不循环链表等等,虽然结构很多,但是我们实际最常用的还是无头单向非循环链表带头双向循环链表

单向或者双向链表

带头链表

循环链表

链表的一些特点

**1.无头单向非循环链表:**结构简单,一般不会单独用来存数据。实际中更是多为其他数据结构的子结构。

**带头双向循环链表:**机构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。

链表的理解

链表的代码结是这样定义的:

struct Node{int data; // 用来存放数据struct Node* next; // 存放下一个节点的地址,用于找到下一个节点
}

我在学习链表的时候对于next的理解一直很困惑,后面突然顿悟,next就是指向下一个节点的地址。我们知道,指针是存放地址的,通过这个地址我们能访问到那个位置的数据。而这个next就是存放下一个节点地址的,通过这个地址,我们就能找到下一个节点。

单链表的实现

链表的操作和顺序表的操作是差不多的,无非是增删改查,这一系列操作。先看看我们要实现的功能

typedef int SLDataType;// 定义链表的结构
typedef struct SListNode {SLDataType data;struct SListNode* next;}SListNode;// 创建一个新节点
SListNode* BuyNewNode(SLDataType x);// 尾插
void SListPushBack(SListNode** pphead, SLDataType x);// 头插
void SListPushFront(SListNode** pphead, SLDataType x);// 尾删
void SListPopBack(SListNode** pphead);// 头删
void SListPopFront(SListNode** pphead);// 打印链表
void SListPrint(SListNode* pphead);// 单链表查找
SListNode* SListFind(SListNode* plist, SLDataType x);// 单链表在pos位置之后插入x
void SListInsertAfter(SListNode* pos, SLDataType x);// 单链表删除pos位置之后的值
void SListEraseAfter(SListNode* pos);// 单链表的销毁
void SListDestory(SListNode* plist);

首先我们得先把链表的结构给定义出来,就是用结构,定义一个链表结点的结构。如下图,我们要把一个结点划分为两个部分,即data和next部分。data部分用来存储数据,next用来存放下一个结点的位置,也就是用来将结点“链接起来”。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xasr70N8-1636910284535)(D:\blogs\结点.png)]

// 链表结点的定义
typedef struct SListNode {SLDataType data;struct SListNode* next; // 因为结点是SListNode类型,所以next得是SListNode*}SListNode;

在定义好结点的结构之后,就得创建结点,我们可以将它封装到一个函数中

SListNode* BuyNewNode(SLDataType x) {SListNode* tmp = (SListNode*)malloc(sizeof(SListNode)); // 为结点申请一块空间// 给成员变量赋值tmp->data = x;tmp->next = NULL;return tmp;
}
// 使用创建结点的函数
int main(){SListNode* node = BuyNewNode(2);return 0;
}

这样我们就的到了单链表的第一个结点,接着就是不断地在这个结点后面插入数据 ,就形成的单链表。下面我们看看几种插入数据的方法。

// 尾插法
void SListPushBack(SListNode** pphead, SLDataType x) {if (*pphead == NULL) {*pphead = BuyNewNode(x);}else {SListNode* tail = *pphead;while (tail->next) {tail = tail->next;};tail->next = BuyNewNode(x);}
}

尾插法,故名思意就是每次都将数据插入到链表的尾部。所以,我们定义了一个tail指针,用它来找到链表的尾部。找的方式就是通过循环来遍历链表tail = tail->next;,这段代码就是让tail指针指向tail的下一个结点,实现遍历。


头插法

// 头插
void SListPushFront(SListNode** pphead, SLDataType x) {if (*pphead == NULL) {*pphead = BuyNewNode(x);}else {SListNode* tmp = BuyNewNode(x);tmp->next = *pphead;*pphead = tmp;}
}

头插法,正好和尾插相反,头插是将新结点插入到链表的最前面,然后返回新节点的地址


尾删

// 尾删
void SListPopBack(SListNode** pphead) {if (*pphead == NULL) {return;}if ((*pphead)->next == NULL) {free(*pphead);*pphead = NULL;}else {SListNode* tail = *pphead;while (tail->next->next) {tail = tail->next;}free(tail->next);tail->next = NULL;}
}

尾删和尾插一样,都需要一个指针来遍历链表,让tail指向最后一个结点的前一个位置,先把最后一个结点free掉,然后再将tail的next指向空。


// 头删
void SListPopFront(SListNode** pphead) {if (*pphead == NULL) {return;}SListNode* tmp = *pphead;*pphead = (*pphead)->next;free(tmp);tmp = NULL;
}

头删就是将最前面的一个结点删掉,所以我们需要先将头结点的地址保存起来,然后让头结点指向它的下一个结点,最后在把结点给free掉


// 单链表查找
SListNode* SListFind(SListNode* plist, SLDataType x) {if (plist == NULL) {return NULL;}SListNode* tmp = plist;while (tmp) {if (tmp->data == x) {break;}else {tmp = tmp->next;}}return tmp;
}

单链表的查找就很简单了,就是把单链表遍历一下,看看有没有哪个结点的data部分和x是相等的,如果有就返回这个结点的地址,否则返回空。


接下来就是单链表的随机插入和删除,这里的随机不是说,听天由命的让电脑选一个位置插入到链表中,而是,我们自己想把它插到哪就插到哪。

// 单链表在pos位置之后插入x
void SListInsertAfter(SListNode* pos, SLDataType x) {assert(pos);SListNode* newnode = BuyNewNode(x);newnode->next = pos->next;pos->next = newnode;
}
// 单链表删除pos位置之后的值
void SListEraseAfter(SListNode* pos) {assert(pos);if (pos->next == NULL) {return;}SListNode* tmp = pos->next;pos->next = tmp->next;free(tmp);tmp = NULL;}

当我们不用单链表的时候一定要将它销毁,把申请的空间给释放掉

// 单链表的销毁
void SListDestory(SListNode* plist) {assert(plist);SListNode* prev = plist;SListNode* cur = plist->next;while (cur) {free(prev);prev = cur;cur = cur->next;}free(prev);prev = NULL;
}

下次分享双向带头环形链表,那是一个很棒的结构。

C语言数据结构单链表链表相关推荐

  1. C语言中用链表构建栈讲解,C语言数据结构之使用链表模拟栈的实例

    C语言数据结构之使用链表模拟栈的实例 以下是"使用链表模拟栈"的简单示例: 1. 用C语言实现的版本 #include #include typedef char datatype ...

  2. C语言数据结构 单链表的建立、遍历、查找、插入和删除操作

    参考文献 本博文为半摘记性质 -- 声明:全文主干部分摘自 [1] 杨智明. 数据结构(C语言版)[M]. 第一版. 北京:北京理工大学出版社, 2016. [2] 严蔚敏, 李冬梅, 吴伟民. 数据 ...

  3. C语言-数据结构-单链表的初始化,插入和输出

    [问题描述] 设有头结点单链表,实现单链表的初始化.插入和输出算法. [输入形式] 第一行输入一个N(N大于等于1,小于1000),一个M(N大于等于1,小于1000): 第二行输入N个整数,以空格作 ...

  4. c语言数据结构单链表

    #include<stdio.h> #include<stdlib.h> typedef int elemtype; typedef struct LNode {     el ...

  5. c语言单链表功能,[数据结构]单链表(C语言)的各种功能

    06-03阅读200,000 + 链表是一种常见的基本数据结构,在此充分利用了结构指针. 链表可以动态存储和分配,即链表是一个功能非常强大的数组. 他可以在节点中定义多种数据类型,并可以根据需要随意添 ...

  6. 数据结构-单链表基本操作(C语言实现)

    参考书:王道考研数据结构 (此贴为博主学习408的笔记,因博主也是学习者,个人总结如有错误欢迎指正.如有侵权请告知,马上删除致歉)​​ 单链表定义 单链表是线性表的链式存储,通过一组任意的存储单元来存 ...

  7. c语言将一个已知头结点的单链表逆序_C语言数据结构实现链表逆序并输出

    C语言数据结构实现链表逆序并输出 将一个链表逆序并输出.我用了两种方法来实现,第一种是借助了一个新的空链表:第二种是在原来链表的基础上直接实现逆序. 实例代码: 头文件: #include #incl ...

  8. 用c语言实现单链表的初始化,建表,查找,求长度,插入,删除等操作,【YTU+2430+C语言习题+链表建立+插入+删除+输(5)...

    的打印.判断链表是否为空.计算链表长度.插入节点.删除节点.删除整个链表.(2) 线性表adt顺序存储实现中的创建.查找.插入和删除等基本操作及相关算法,线性表adt链式存储实现中单链表.循环链表和双 ...

  9. php链表和联表的区别,PHP_浅谈PHP链表数据结构(单链表),链表:是一个有序的列表,但 - phpStudy...

    浅谈PHP链表数据结构(单链表) 链表:是一个有序的列表,但是它在内存中是分散存储的,使用链表可以解决类似约瑟夫问题,排序问题,搜索问题,广义表 单向链表,双向链表,环形链表 PHP的底层是C,当一个 ...

最新文章

  1. Hadoop-2.2.0学习之一Hadoop-2.2.0变化简介
  2. Qt安装和QML HelloWord程序
  3. 推荐Datawhale整理的秋招求职攻略
  4. Centos下MySql用户管理
  5. 一张图解决Android Studio 项目运行按钮灰色
  6. PROTEUS元件库元件称呼 .
  7. php数字补零的两种方法
  8. raspberry pi_如何使用Raspberry Pi构建数字针Kong相机
  9. android搭建客户端,用Android搭建客户端 手机和服务器交互开发实例
  10. bzoj1041 [HAOI2008]圆上的整点 gcd
  11. React学习笔记—表单
  12. NP、OSPF 故障排除
  13. tcp 重发 应用层重传
  14. JavaWeb-Web请求过程
  15. 常用webserver 比较
  16. android什么叫服务器,Android系统中神秘的Bootloader究竟是什么
  17. linux系统FW升降级步骤,使用fwupd为Ubuntu 18.04系统更新固件的方法
  18. 【软件推荐】使用手机和平板作电脑副屏扩展
  19. 思科交换机配置试题_cisco交换机配置简单教程.doc
  20. php 中margin-top,margin-top是什么意思?

热门文章

  1. 新闻丨智链ChainNova出席2018数字泰国年会 展示中国落地案例
  2. Baidu NLP词法分析工具LAC使用体验
  3. 人工智能产品经理的新起点
  4. 京东-按图搜索(拍立淘)
  5. 爬虫实战二:百度贴吧之全吧搜索
  6. 湿气重的人多吃这5种食材,排毒祛湿,让你越来越瘦!
  7. codeforces 1536B Prinzessin der Verurteilung
  8. cdn.bootcss.com老是挂掉,解决方法
  9. 网页箭头特效:用CSS写的网页导航向上箭头
  10. Java程序猿的毕业设计初稿怎么写?