目录

0.结构体定义

1.初始化

2.尾插

3.打印

4.头插

5.任意位置插入前面位置

6.尾删

7.头删

8.链表长度

9.任意位置删除当前位置

10. 销毁


双向带头循环链表:结构复杂,操作简单

0.结构体定义

这里方便浏览,特地没有将int类型重命名为TLDateType

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>struct ListNode
{int val;struct ListNode* prev;struct ListNode* next;
};

1.初始化

  1. 带头需要初始化一个哨兵位头结点
  2. 传二级指针
  3. 初始化自己的prev和next都指向自己
void ListInit(struct ListNode** pphead)
{struct ListNode* Guard = (struct ListNode*)malloc(sizeof(struct ListNode));if (Guard == NULL){perror("ListInit");return;}*pphead = Guard;Guard->next = Guard;Guard->prev = Guard;
}

2.尾插

  1. 一级指针
  2. 直接prev找尾
  3. 即是无首元结点,也可(头结点自环)
struct ListNode* BuyListNode(int x)
{struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));if (newnode == NULL){perror("BuySListNode");return NULL;}newnode->val = x;newnode->prev = NULL;newnode->next = NULL;return newnode;
}void ListPushBack(struct ListNode* phead,int x)
{assert(phead);struct ListNode* newnode = BuyListNode(x);struct ListNode* tail = phead->prev;newnode->next = phead;phead->prev = newnode;tail->next = newnode;newnode->prev = tail;
}

3.打印

  1. 可assert断言(建议单链表不用断言)---头结点
  2. 起始条件cur=phead->next;
  3. 循环终止条件cur==phead
void ListPrint(struct ListNode* phead)
{assert(phead);struct ListNode* cur = phead->next;while (cur != phead){printf("%d->", cur->val);cur = cur->next;}printf("NULL\n");
}

4.头插

  1. 一级指针
  2. 即是无首元结点,也可(头结点自环)
void ListPushFront(struct ListNode* phead,int x)
{assert(phead);struct ListNode* newnode = BuyListNode(x);struct ListNode* next = phead->next;newnode->next = next;next->prev = newnode;phead->next = newnode;newnode->prev = phead;}

5.任意位置插入前面位置

  1. 因为有prev,前插不同phead
  2. 尾插,头插就用ListInsert传不同pos参数
  3. 如果pos传phead,就相当于于是尾插
  4. 如果pos传phead->next,就相当于于是头插
void ListInsert(struct ListNode* pos, int x)
{assert(pos);struct ListNode* newnode = BuyListNode(x);struct ListNode* prev = pos->prev;prev->next = newnode;newnode->prev = prev;newnode->next = pos;pos->prev = newnode;
}头插:ListNode(phead->next,x);
尾插:ListNode(phead,x);

6.尾删

  1. 不为空,!ListEmpty(plhead)
  2. prev,tail,phead
bool ListEmpty(struct ListNode* phead)
{return phead->next == phead;
}void ListPopBack(struct ListNode* phead)
{assert(phead);assert(!ListEmpty(phead));struct ListNode* tail = phead->prev;struct ListNode* prev = tail->prev;prev->next = phead;phead->prev = prev;free(tail);tail = NULL;
}

7.头删

  1. 不为空,!ListEmpty(plhead)
  2. phead,first,second
void ListPopFront(struct ListNode* phead)
{assert(phead);assert(!ListEmpty(phead));struct ListNode* first = phead->next;struct ListNode* second = first->next;phead->next = second;second->prev = phead;free(first);first = NULL;
}

8.链表长度

  1. 起始条件:cur=phead->next
  2. 终止条件:cur!=phead;
size_t ListSize(struct ListNode* phead)
{size_t size = 0;struct ListNode* cur = phead->next;while (cur != phead){++size;cur = cur->next;}return size;
}

9.任意位置删除当前位置

  1. 不为空,!ListEmpty(plhead)
  2. 尾删,头删就用ListErase传不同pos参数
  3. 如果pos传phead->prev,就是尾删
  4. 如果pos传phead->next,就是头删
void ListErase(struct ListNode* pos)
{assert(pos);struct ListNode* prev = pos->prev;struct ListNode* next = pos->next;prev->next = next;next->prev = prev;free(pos);pos = NULL;
}

10. 销毁

  1. 看是否保留哨兵头,来传一级或二级指针
  2. 先保留哨兵头作为判断循环条件,最后决定是否释放哨兵头
void ListDestory(struct ListNode** pphead)
{assert(pphead);struct ListNode* cur = (*pphead)->next;while (cur != *pphead){struct ListNode* next = cur->next;free(cur);cur = next;}free(*pphead);*pphead = NULL;
}

制作不易,敬请三连

【数据结构初阶】双向带头循环链表原来是纸老虎,结构复杂,操作简单相关推荐

  1. 外强中干——双向带头循环链表

    前言:众所周知,链表有八种结构,由单向或双向,有头或无头,循环或不循环构成.在本篇,将介绍8种链表结构中最复杂的--双向带头循环链表.听着名字或许挺唬人的,但实际上双向带头循环链表实现起来比结构最简单 ...

  2. 数据结构------双向带头循环链表

    目录 1.什么是双向带头循环链表?模型. 2.1 创建结点函数 2.2初始化 3.尾插实现 3.1图示 3.2尾插 4.打印函数实现 4.1打印函数 5.思考为啥是一级指针 6.头插实现 6.2实现代 ...

  3. 【数据结构--双向带头循环链表(链表中的老大哥)】

    双向带头循环链表及相关OJ

  4. 数据结构初阶(4)(OJ练习【判断链表中是否有环、返回链表入口点、删除链表中的所有重复出现的元素】、双向链表LinkedList【注意事项、构造方法、常用方法、模拟实现、遍历方法、顺序表和链表的区别)

    接上次博客:数据结构初阶(3)(链表:链表的基本概念.链表的类型.单向不带头非循环链表的实现.链表的相关OJ练习.链表的优缺点 )_di-Dora的博客-CSDN博客 目录 OJ练习 双向链表--Li ...

  5. 链表界的“扛把子”—双向带头循环链表

    目录 一:链表的分类 二:链表的实现 2-1:创建链表 2-2:创建新的结点 2-3:初始化链表 2-4:打印链表 2-5:销毁链表 三:链表的核心功能 3-1:尾插 3-2:尾删 3-3:链表查找 ...

  6. 双向带头循环链表的实现

    双向带头循环链表 双向带头循环链表 结构讲解 期望实现功能 创建链表和头节点作用 头插和头删 头插 头删 尾插与尾删 尾插 尾删 pos 删除和插入 插入 删除 打印和查找 整体代码 这个数据结构可以 ...

  7. 【双向带头循环链表】

    双向带头循环链表 0.链表中每个节点的基本结构 1.初始化链表(创建哨兵位头节点) 2.申请新节点 3.尾插节点 4.尾删节点 5.头插节点 6.头删节点 7.寻找pos位置的节点 8.在pos位置之 ...

  8. 双向带头循环链表-实现思路+图解

    目录 一.何为双向循环链表? 1.何为'双向'? 2.何为'带头'? 3.何为'循环'? 二.如何实现双向带头循环链表? 1.基本结构-结点的创建 2.创建哨兵位结点 3.链表的增删查改 一.何为双向 ...

  9. 双向带头循环链表的(增删查改)的实现

    文章目录 一.双向带头循环链表 构成 二.双向带头循环链表的实现 1.函数的定义和结构体的创建--list.h 2.函数的调用--list.c 3. 双向带头循环链表与单链表的传递参数区别 4.双向带 ...

最新文章

  1. 为什么要开发抽象编程语言(APL)?
  2. 计算几何-经典算法-凸包
  3. 论文笔记 Hierarchical Reinforcement Learning for Scarce Medical Resource Allocation
  4. 【收藏】IntelliJ Idea中配置JavaFX Scene Builder
  5. 关于Direct2D
  6. Mac 登陆 去掉 其他用户
  7. 算法训练 瓷砖铺放 递归
  8. 【实践】58同城本地服务推荐系统演进
  9. [20180503]珅与分隔符.txt
  10. 文字处理控件功能比较:TX Text Control vs. RichTextBox
  11. 调用css样式是不调用某个属性,CSS选择器可以引用另一个选择器属性吗?
  12. 3lcd和dlp怎么选,DLP和3LCD投影机的选择对比
  13. 推荐几个最好用的CRM软件,本人亲测
  14. 单元测试引入hsqldb探索
  15. Lync部署之Lync Mobile服务器端的外网设置
  16. C++基础数论—————容斥原理
  17. 禁止搜索引擎收录的方法
  18. MPU6050原始数据分析——学习笔记
  19. 4.8 期货每日早盘操作建议
  20. Python词云实现

热门文章

  1. 修改smac协议成lmac
  2. 算法代码备忘录(2)
  3. 数据转移高效方法(oracle)
  4. 微信开发者工具的版本管理如何使用
  5. c3p0和dbcp的使用和区别
  6. Android开发— Android API Levels
  7. Simulink 快速入门(一)--Simulink 模块图
  8. 天池AI大赛 智能制造预测赛题
  9. 15种可切换404自适应页面源码
  10. Unity 运行状态下动态保存 预制体/预制体上脚本参数