数据结构 —— 顺序表
数据结构 —— 单链表
数据结构 —— 双向链表
数据结构 —— 栈
数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。数据结构是一种十分优秀的解决实际问题的模板,是先进思想的结晶。博主将会用代码结合大量图解,对数据结构进行深度剖析,以便大家更好的学习数据结构的思想。
城市对外交通实现了从一个城市到另一个城市的道路,但今天所讨论的仅限于一个城市连接其他两个城市的回环交通结构。
城市对外交通指的是城市与城市之间的交通,是连接城市与城市之间往返的重要路径

城市回环交通结构与本文将的内容极其相似,我们由城市的回环交通来引入双向带头循环链表

双向链表的引入:既能指向前一个节点又指向下一个节点存储内容地址
链表:由 n 个节点链接成一个链表,即线性表的链式存储结构
双向链表:双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱
节点:

双向链表的结构类型
typedef int LTDateType; //便于更改存储类型
typedef struct ListNode {
LTDateType data; //数据域:存储数据元素信息
struct ListNode *prev; //指针域:存储上一个节点信息
struct ListNode *next; //指针域:存储下一个节点信息
} ListNode;
存储:用动态开辟的
sizeof(ListNode)大小的一块空间进行存储

动态开辟一块
sizeof(ListNode)大小的空间进行存储
// 动态申请一个结点
ListNode *BuyListNode(LTDateType x) {
ListNode *node = (ListNode *) malloc(sizeof(ListNode));
node->data = x;
node->prev = NULL;
node->next = NULL;
return node;
}

创建返回链表的哨兵位
// 创建返回链表的哨兵位
ListNode *ListInit() {
ListNode *pHead = BuyListNode(-1);
pHead->prev = pHead;
pHead->next = pHead;
return pHead;
}

双向链表查找指定数据
// 双向链表查找
ListNode *ListFind(ListNode *pHead, LTDateType x) {
assert(pHead);
ListNode *curr = pHead->next;
while (curr != pHead) {
if (curr->data == x) {
return curr;
}
curr = curr->next;
}
return NULL;
}

双向链表在指定位置 pos 插入 x
// 双向链表在pos位置插入x
void ListInsert(ListNode *pos, LTDateType x) {
assert(pos);
ListNode *newNode = BuyListNode(x);
ListNode *prev = pos->prev;
newNode->prev = prev;
newNode->next = pos;
prev->next = newNode;
pos->prev = newNode;
}

双向链表删除在指定位置 pos
// 双向链表在pos位置删除
void ListErase(ListNode *pos) {
assert(pos);
assert(pos != pos->next);
pos->next->prev = pos->prev;
pos->prev->next = pos->next;
free(pos);
}

双向链表在哨兵位之后的位置插入 x
// 双向链表头插
void ListPushFront(ListNode *pHead, LTDateType x) {
ListInsert(pHead->next, x);
}

双向链表删除哨兵位的后一个节点
// 双向链表头删
void ListPopFront(ListNode *pHead) {
ListErase(pHead->next);
}

双向链表在哨兵位之前的位置插入 x
// 双向链表尾插
void ListPushBack(ListNode *pHead, LTDateType x) {
ListInsert(pHead, x);
}

双向链表删除哨兵位的前一个节点
// 双向链表尾删
void ListPopBack(ListNode *pHead) {
ListErase(pHead->prev);
}

计算双向链表的大小
// 计算大小
int ListSize(ListNode *pHead) {
ListNode *curr = pHead->next;
int size = 0;
while (curr != pHead) {
size++;
curr = curr->next;
}
return size;
}
销毁双向链表,请手动置空
// 销毁(手动置空)
void ListDestory(ListNode *pHead) {
ListNode *curr = pHead->next;
while (curr != pHead) {
ListNode *next = curr->next;
free(curr);
curr = next;
}
free(pHead);
}
双向链表是解决实际问题时极其常用的一种数据结构,是非常重要的解决问题的方式。双向链表的各种接口的复现,有利于更好的学习数据结构的思想,有利于开阔视野,学习前辈的智慧结晶。对我们后续解决实际问题也会有很大帮助。