赞
踩
目录
个人主页:深情秋刀鱼@-CSDN博客
数据结构专栏:数据结构与算法
循环链表这个轮回的思想很有意思。它强调了不管你今生是贫是富,如果持续行善积德,下辈子就会好过,反之就会遭到报应。
就像每个人的人生一样,欲收获就得付出代价。双向链表既然是比单链表多了如可以反向遍历查找的数据结构,那么也就要付出一些小的代价。
链表的结构复杂多样,总计有如下八种形式。
虽然有这么多的链表的结构,但是我们实际中最常⽤还是两种结构: 单链表 和 双向带头循环链表。1. ⽆头单向⾮循环链表:结构简单,⼀般不会单独⽤来存数据。实际中更多是作为其他数据结 构的⼦结构,如哈希桶、图的邻接表等等。另外这种结构在笔试⾯试中出现很多。2. 带头双向循环链表:结构最复杂,⼀般⽤在单独存储数据。实际中使⽤的链表数据结构,都 是带头双向循环链表。另外这个结构虽然结构复杂,但是使⽤代码实现以 后会发现结构会带 来很多优势,实现反⽽简单了。
对于带头和不带头,在学习单链表是我们将其理解为链表的头节点(链表的第一个节点),这种称呼很不严谨,在本节中的带头和不带头指的是在该链表中书否含有哨兵结点,哨兵结点在双向链表中是名副其实的头节点,哨兵节点内不存储任何有效的数据,他的唯一作用是防止在遍历链表时进入死循环。
- //双向链表的定义
- typedef int LTDataType;
-
- //定义双向链表的节点
- typedef struct ListNode
- {
- LTDataType data;//数据域
- struct ListNode* next;//指向后继节点的指针
- struct ListNode* prev;//指向前驱节点的指针
- }ListNode;
- ListNode* LTbuyNode(LTDataType x)
- {
- ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
- if (newNode == NULL)
- {
- perror("malloc fail!");
- exit(1);
- }
- newNode->data = x;
- newNode->next = newNode;
- newNode->prev = newNode;//创建的新节点指向自身
- return newNode;
- }
- //初始化
- void LTinit(ListNode** pphead)
- {
- *pphead = LTbuyNode(-1);//哨兵位(不存储有效值)
- }
- //尾插
- void LTpushBack(ListNode* phead, LTDataType x)
- {
- assert(phead);
- ListNode* node = LTbuyNode(x);
- node->prev = phead->prev;
- node->next = phead;
- phead->prev->next = node;
- phead->prev = node;
- }
- //打印
- void LTprint(ListNode* phead)
- {
- assert(phead);
- ListNode* pcur = phead->next;
- while (pcur != phead)
- {
- printf("%d->", pcur->data);
- pcur = pcur->next;
- }
- printf("head\n");
- }
- //头插
- void LTpushFront(ListNode* phead, LTDataType x)
- {
- assert(phead);
- ListNode* node = LTbuyNode(x);
- node->prev = phead;
- node->next = phead->next;
- phead->next->prev = node;
- phead->next = node;
- }
- //尾删
- void LTpopBack(ListNode* phead)
- {
- assert(phead && phead->next != phead);//链表不为空
- ListNode* pcur = phead->prev;
- phead->prev->prev->next = phead;
- phead->prev = phead->prev->prev;
- free(pcur);
- pcur = NULL;
- }
- //头删
- void LTpopFront(ListNode* phead)
- {
- assert(phead && phead->next != phead);
- ListNode* pcur = phead->next;
- phead->next->next->prev = phead;
- phead->next = phead->next->next;
- free(pcur);
- pcur = NULL;
- }
- //pos位置之后插入数据
- void LTinsert(ListNode* pos, LTDataType x)
- {
- assert(pos);
- ListNode* node = LTbuyNode(x);
- pos->next->prev = node;
- node->prev = pos;
- node->next = pos->next;
- pos->next = node;
- }
- //删除pos节点
- void LTerase(ListNode* pos)
- {
- assert(pos);
- pos->prev->next = pos->next;
- pos->next->prev = pos->prev;
- free(pos);
- pos = NULL;
- }
- //查找
- ListNode* LTfind(ListNode* phead, LTDataType x)
- {
- assert(phead && phead->next != phead);
- ListNode* pcur = phead->next;
- while (pcur != phead)
- {
- if (pcur->data == x)
- {
- printf("找到了!\n");
- return pcur;
- }
- pcur = pcur->next;
- }
- printf("没有找到!\n");
- return NULL;
- }
- //销毁
- void LTdestroy(ListNode* phead)
- {
- assert(phead);
- ListNode* pcur = phead->next;
- while (pcur != phead)
- {
- ListNode* next = pcur->next;
- free(pcur);
- pcur = next;
- }
- free(phead);
- phead = NULL;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。