链表(Linked list)是一种线性表,可是并不会在物理存储上按线性的顺序存储数据,而是在每个节点里存到下一个节点的指针(Pointer)。因为没必要须按顺序存储,链表的插入和删除操做能够达到O(1)的复杂度。本文将讲解单向链表和双向链表,其中双向链表会给出部分关键代码实现。node
单向链表(单链表)是链表的一种,它由节点组成,每一个节点都包含下一个节点的指针,下图就是一个单链表,表头为空,表头的后继节点是"结点10"(数据为10的结点),"节点10"的后继结点是"节点20"(数据为10的结点),...算法
咱们看看单链表删除节点的操做,好比说下面这个单链表中咱们要删除"节点30"。编程
删除以前:"节点20" 的后继节点为"节点30",而"节点30" 的后继节点为"节点40"。缓存
删除以后:"节点20" 的后继节点为"节点40"。服务器
咱们再来看看单链表添加节点的操做,好比说下面这个单链表中咱们在"节点10"与"节点20"之间添加"节点15"数据结构
添加以前:"节点10" 的后继节点为"节点20"。并发
添加以后:"节点10" 的后继节点为"节点15",而"节点15" 的后继节点为"节点20"。ide
双向链表(双链表)是链表的一种。和单链表同样,双链表也是由节点组成,它的每一个数据结点中都有两个指针,分别指向直接后继和直接前驱。因此,从双向链表中的任意一个结点开始,均可以很方便地访问它的前驱结点和后继结点。通常咱们都构造双向循环链表。线程
双链表的示意图以下:设计
表头为空,表头的后继节点为"节点10"(数据为10的节点);"节点10"的后继节点是"节点20"(数据为10的节点),"节点20"的前继节点是"节点10";"节点20"的后继节点是"节点30","节点30"的前继节点是"节点20";...;末尾节点的后继节点是表头。
不难看出,双向链表的节点定义能够用一个下面的结构体表示:
//双向链表节点结构 typedef struct dlink_node { struct dlink_node *prev; struct dlink_node *next; void *val; //能存储任意类型数据 }node;
咱们看看双向链表删除节点的操做,好比说下面这个单链表中咱们要删除"节点30"。
删除以前:"节点20"的后继节点为"节点30","节点30" 的前继节点为"节点20"。"节点30"的后继节点为"节点40","节点40" 的前继节点为"节点30"。
删除以后:"节点20"的后继节点为"节点40","节点40" 的前继节点为"节点20"。
双向链表删除节点的关键代码以下:
//删除节点pindex pindex->next->prev = pindex->prev; pindex->prev->next = pindex->next; free(pindex); //注意释放节点
咱们再来看看双向链表添加节点的操做,好比说下面这个双向链表在"节点10"与"节点20"之间添加"节点15"
添加以前:"节点10"的后继节点为"节点20","节点20" 的前继节点为"节点10"。
添加以后:"节点10"的后继节点为"节点15","节点15" 的前继节点为"节点10"。"节点15"的后继节点为"节点20","节点20" 的前继节点为"节点15"。
双向链表添加节点的关键代码以下:
//将pnode节点插入到pindex以前 pnode->prev = pindex->prev; pnode->next = pindex; pindex->prev->next = pnode; pindex->prev = pnode;
【福利】本身搜集的网上精品课程视频分享(上)
【系统设计】LRU缓存
【协议森林】05 我尽力 (IP协议详解)
【数据结构与算法】 通俗易懂讲解 位排序
【C++札记】C++11并发编程(一)开启线程之旅
【C++札记】C/C++指针使用常见的坑
【C++札记】静态库和动态库详解(上)
码农有道,为您提供通俗易懂的技术文章,让技术变的更简单!