数据结构 – 链表

文章目录

  • 数据结构 -- 链表
  • 一、单链表
    • 1.概念及结构
    • 2.接口实现
    • 3.特性总结
  • 二、双向带头循环链表
    • 1.概念及结构
    • 2.接口实现
    • 3.特性总结
  • 总结

一、单链表

1.概念及结构

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

其结构定义如下:

typedef int SLTDataType;typedef struct SListNode
{SLTDataType data;struct SListNode* next;
}SLTNode;

2.接口实现

代码如下:
1.直接创建节点

void SLTTest1()
{//创建结点SLTNode* n1 = (SLTNode*)malloc(sizeof(SLTNode));assert(n1);SLTNode* n2 = (SLTNode*)malloc(sizeof(SLTNode));assert(n2);SLTNode* n3 = (SLTNode*)malloc(sizeof(SLTNode));assert(n3);SLTNode* n4 = (SLTNode*)malloc(sizeof(SLTNode));assert(n4);n1->data = 1;n2->data = 2;n3->data = 3;n4->data = 4;n1->next = n2;n2->next = n3;n3->next = n4;n4->next = NULL;SListPrint(n1); SListPushBack(&n1, 5);SListPrint(n1);
}

2.创建新节点

SLTNode* BuySListNode(SLTDataType x)//返回值是新节点的地址
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));assert(newnode);newnode->data = x;newnode->next = NULL;return newnode;
}

3.打印

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

4.尾插

void SListPushBack(SLTNode** pphead, SLTDataType x)
{assert(pphead);SLTNode* newnode = BuySListNode(x);if (*pphead == NULL)//当链表是空的时候,直接将指向头结点的指针指向创建的新结点//但是由于是函数传参,若需要改变原头结点指针的指向,则需要传二级指针,并在函数中解引用进行改变{*pphead = newnode;}else//否则,找到尾结点{SLTNode* tail = *pphead;while (tail->next != NULL){tail = tail->next;}tail->next = newnode;}
}

5.头插

void SListPushFront(SLTNode** pphead, SLTDataType x)//头插也需要改变头结点指针的指向,所以也传二级指针
{assert(pphead);SLTNode* newnode = BuySListNode(x);newnode->next = *pphead;*pphead = newnode;
}

6.尾删

void SListPopBack(SLTNode** pphead)//当链表只有一个节点的时候,也需要改变头结点指针的指向,所以传二级指针
{assert(pphead);assert(*pphead);//若头结点指向空,则代表链表是空的,在此断言if ((*pphead)->next == NULL)//只有一个结点{free(*pphead);*pphead = NULL;}else{SLTNode* tailPrev = NULL;//用来保存尾结点的前一个结点的指针SLTNode* tail = *pphead;while (tail->next != NULL)//找到尾结点的前一个结点{tailPrev = tail;tail = tail->next;}free(tail);tailPrev->next = NULL;}
}

7.头删

//头删
void SListPopFront(SLTNode** pphead)
{assert(pphead);assert(*pphead);SLTNode* next = (*pphead)->next;//保存头节点的下一个节点指针free(*pphead);//释放头节点指向的空间*pphead = next;//头节点指针指向下一个节点
}

8.查找

//查找
SLTNode* SListFind(SLTNode* phead, SLTDataType x)
{SLTNode* cur = phead;while (cur){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}

9.在指定位置之前插入

void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pos);assert(pphead);if (pos == *pphead)//如果是头节点{SListPushFront(pphead, x);}else{SLTNode* prev = *pphead;//保存pos前一个节点的指针while (prev->next != pos)//找到pos前一个节点的指针{prev = prev->next;}SLTNode* newnode = BuySListNode(x);prev->next = newnode;newnode->next = pos;}
}

10.删除当前位置的节点

void SListErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead);assert(pos);if (*pphead == pos)//如果是头节点{SListPopFront(pphead);}else{SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}prev->next = pos->next;free(pos);}
}

3.特性总结

链表的优点:任意位置插入删除的时间复杂度低,空间按需申请和释放;
缺点:不支持下标随机访问。

二、双向带头循环链表

1.概念及结构

双向带头循环链表是在单链表的基础上增加了哨兵位,并且将增加了一个指向前一个节点的指针,首尾节点循环。

其结构定义如下:

typedef int LTDataType;typedef struct ListNode
{struct ListNode* prev;struct ListNode* next;LTDataType data;
}LTNode;

2.接口实现

代码如下:
1.创建结点

LTNode* BuyListNode(LTDataType x)
{LTNode* node = (LTNode*)malloc(sizeof(LTNode));if (node == NULL){perror("malloc");exit(-1);}node->data = x;node->next = NULL;node->prev = NULL;return node;
}

2.初始化

LTNode* ListInit()
{LTNode* phead = BuyListNode(0);phead->next = phead;phead->prev = phead;return phead;
}

3.打印

void ListPrint(LTNode* phead)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){printf("%d ", cur->data);cur = cur->next;}printf("\n");
}

4.在pos之前插入 x

void ListInsert(LTNode* pos, LTDataType x)
{assert(pos);LTNode* newnode = BuyListNode(x);LTNode* prev = pos->prev;pos->prev = newnode;newnode->next = pos;newnode->prev = prev;prev->next = newnode;
}

5.删除pos位置

void ListErase(LTNode* pos)
{assert(pos);LTNode* next = pos->next;LTNode* prev = pos->prev;prev->next = next;next->prev = prev;free(pos);
}

6.尾插

void ListPushBack(LTNode* phead, LTDataType x)
{assert(phead);ListInsert(phead, x);
}

7.头插

void ListPushFront(LTNode* phead, LTDataType x)
{assert(phead);ListInsert(phead->next, x);
}

8.尾删

void ListPopBack(LTNode* phead)
{assert(phead);assert(phead->next != phead);//防止链表删空,把头结点删除,出现野指针ListErase(phead->prev);
}

9.头删

void ListPopFront(LTNode* phead)
{assert(phead);assert(phead->next != phead);//防止链表删空,把头结点删除,出现野指针ListErase(phead->next);
}

10.判断链表是否为空

bool ListEmpty(LTNode* phead)
{assert(phead);return phead->prev == phead;//若链表为空,则头节点的前向指针prev就指向自己
}

11.计算链表长度

int ListSize(LTNode* phead)
{assert(phead);LTNode* cur = phead->next;int size = 0;while (cur != phead)//从哨兵位头结点开始转一圈{size++;cur = cur->next;}return size;
}

10.双向链表销毁

void ListDestory(LTNode* phead)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){LTNode* next = cur->next;ListErase(cur);cur = next;}free(phead);phead == NULL;
}

3.特性总结

双向链表的插入删除比较简单。


总结

本文简单介绍了单链表和双向带头循环链表的结构、实现即特点。

数据结构 -- 链表相关推荐

  1. 初学数据结构--链表

    2019独角兽企业重金招聘Python工程师标准>>> 前言 在这一章,我将介绍另外一种非常重要的线性数据结构--链表.在之前介绍的动态数组,栈和队列这三种数据结构,底层其实依托于静 ...

  2. C++数据结构链表的基本操作

    这篇文章主要为大家介绍了C++数据结构链表基本操作的示例过程有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪 首先创建好一个节点 typedef struct node {in ...

  3. c语言仓库管理系统链表,仓库管理系统 C语言 C++ 数据结构 链表 课程设计

    仓库管理系统 C语言 C++ 数据结构 链表 课程设计 #include #include #include #include #define MAX 64 typedef struct node{ ...

  4. 数据结构 - 链表 - 面试中常见的链表算法题

    数据结构 - 链表 - 面试中常见的链表算法题 数据结构是面试中必定考查的知识点,面试者需要掌握几种经典的数据结构:线性表(数组.链表).栈与队列.树(二叉树.二叉查找树.平衡二叉树.红黑树).图. ...

  5. 数据结构链表之符号表,Python3实现——8

    数据结构链表之符号表 符号表的介绍 之前章节介绍的顺序表和链表都是一个节点储存一个元素的表,但在日常生活中我们还有很多一次需要储存成对或多个值的情况,例如: 符号表最主要的目的将一对元素,用一个键和一 ...

  6. 数据结构链表之队列,Python3实现——7

    数据结构链表之队列 队列概述 定义:队列是一种基于先进先出(FIFO)的数据结构,队列只能在一段进行插入和删除操作的结构,第一个进入队列的元素在读取时会第一个被读取 队列可以使用顺序表(Python中 ...

  7. 数据结构链表之栈,Python3简单实现——5

    数据结构链表之栈 栈的概述 定义:栈是一种基于先进后出(FILO)的数据结构,是一种只能在一段进行插入和删除操作的特殊线性表. 引入名词:将数据存入栈的动作称为压栈,将数据取出栈的动作称为弹栈 栈的特 ...

  8. 数据结构链表例程_如何掌握RxJava例程的四个结构

    数据结构链表例程 by Ayusch Jain 通过Ayusch Jain 如何掌握RxJava例程的四个结构 (How to get a grip on the four constructs of ...

  9. 数据结构链表代码_代码简介:链表数据结构如何工作

    数据结构链表代码 Here are three stories we published this week that are worth your time: 这是我们本周发布的三个值得您关注的故事 ...

  10. python创建链表实例_python数据结构链表之单向链表(实例讲解)

    python数据结构链表之单向链表(实例讲解) 单向链表 单向链表也叫单链表,是链表中最简单的一种形式,它的每个节点包含两个域,一个信息域(元素域)和一个链接域.这个链接指向链表中的下一个节点,而最后 ...

最新文章

  1. vue下实现textarea类似密码框的功能之探索input输入框keyup,keydown,input事件的触发顺序...
  2. 【quickhybrid】组件(自定义)API的实现
  3. php的引用变量与销毁机制
  4. 图像处理库OpenCV参考网址
  5. java并发之TimeUnit
  6. python中dtypes_关于python:如何通过pandas DataFrame中的列设置dtypes
  7. 锐捷官方提供122套实验题.
  8. win10win键无反应_台式电脑开机主机没反应怎么办 电脑开机主机没反应解决【详解】...
  9. 遥感原理与应用孙家炳_2.2遥感应用模型
  10. ftp服务器复制粘贴文件夹,ftp服务器复制粘贴文件夹
  11. 300. 最长递增子序列(JavaScript)
  12. Myeclipse学习总结(14)——Eclipse/MyEclipse中Java编译时Java反射机形参没有保留问题2种解决方案
  13. python 面试必问,不会真的要打脸~
  14. MySQL分库、分表、分区的区别
  15. RDB 和 AOF 持久化的原理是什么?我应该用哪一个?它们的优缺点? 1
  16. Android手柄数据全解析
  17. Python 树莓派 引脚
  18. android 2k 屏幕 字体模糊,2k显示器上的字体模糊
  19. OneNote笔记备份
  20. 斯坦福大学公开课IOS 7学习笔记 (1)

热门文章

  1. 预装Windows 7的联想笔记本电脑 重新安装XP系统遇到花屏问题的解决方案
  2. 抓球球的机器人应该怎么玩_尖塔奇兵机器人怎么玩 机器人玩法及套路
  3. 如何在Ubuntu20.04上安装RDP远程
  4. 【吐血整理】Hibernate常用的主键生成策略的原理、优缺点、应用场合
  5. shader变体是什么_Shader Variants 打包遇到的问题
  6. 爱奇艺在Hadoop生态中大数据平台实践
  7. python里init什么意思_Python中 __init__的通俗解释是什么?
  8. 北京东方IT电脑救援俱乐部招聘通知
  9. 2019CCPC女生赛
  10. VMware Linux 下安装 Oracle 11gR2 RAC