【数据结构初阶】双向带头循环链表原来是纸老虎,结构复杂,操作简单
目录
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.初始化
- 带头需要初始化一个哨兵位头结点
- 传二级指针
- 初始化自己的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.尾插
- 一级指针
- 直接prev找尾
- 即是无首元结点,也可(头结点自环)
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.打印
- 可assert断言(建议单链表不用断言)---头结点
- 起始条件cur=phead->next;
- 循环终止条件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.头插
- 一级指针
- 即是无首元结点,也可(头结点自环)
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.任意位置插入前面位置
- 因为有prev,前插不同phead
- 尾插,头插就用ListInsert传不同pos参数
- 如果pos传phead,就相当于于是尾插
- 如果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.尾删
- 不为空,!ListEmpty(plhead)
- 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.头删
- 不为空,!ListEmpty(plhead)
- 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.链表长度
- 起始条件:cur=phead->next
- 终止条件: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.任意位置删除当前位置
- 不为空,!ListEmpty(plhead)
- 尾删,头删就用ListErase传不同pos参数
- 如果pos传phead->prev,就是尾删
- 如果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. 销毁
- 看是否保留哨兵头,来传一级或二级指针
- 先保留哨兵头作为判断循环条件,最后决定是否释放哨兵头
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;
}
制作不易,敬请三连
【数据结构初阶】双向带头循环链表原来是纸老虎,结构复杂,操作简单相关推荐
- 外强中干——双向带头循环链表
前言:众所周知,链表有八种结构,由单向或双向,有头或无头,循环或不循环构成.在本篇,将介绍8种链表结构中最复杂的--双向带头循环链表.听着名字或许挺唬人的,但实际上双向带头循环链表实现起来比结构最简单 ...
- 数据结构------双向带头循环链表
目录 1.什么是双向带头循环链表?模型. 2.1 创建结点函数 2.2初始化 3.尾插实现 3.1图示 3.2尾插 4.打印函数实现 4.1打印函数 5.思考为啥是一级指针 6.头插实现 6.2实现代 ...
- 【数据结构--双向带头循环链表(链表中的老大哥)】
双向带头循环链表及相关OJ
- 数据结构初阶(4)(OJ练习【判断链表中是否有环、返回链表入口点、删除链表中的所有重复出现的元素】、双向链表LinkedList【注意事项、构造方法、常用方法、模拟实现、遍历方法、顺序表和链表的区别)
接上次博客:数据结构初阶(3)(链表:链表的基本概念.链表的类型.单向不带头非循环链表的实现.链表的相关OJ练习.链表的优缺点 )_di-Dora的博客-CSDN博客 目录 OJ练习 双向链表--Li ...
- 链表界的“扛把子”—双向带头循环链表
目录 一:链表的分类 二:链表的实现 2-1:创建链表 2-2:创建新的结点 2-3:初始化链表 2-4:打印链表 2-5:销毁链表 三:链表的核心功能 3-1:尾插 3-2:尾删 3-3:链表查找 ...
- 双向带头循环链表的实现
双向带头循环链表 双向带头循环链表 结构讲解 期望实现功能 创建链表和头节点作用 头插和头删 头插 头删 尾插与尾删 尾插 尾删 pos 删除和插入 插入 删除 打印和查找 整体代码 这个数据结构可以 ...
- 【双向带头循环链表】
双向带头循环链表 0.链表中每个节点的基本结构 1.初始化链表(创建哨兵位头节点) 2.申请新节点 3.尾插节点 4.尾删节点 5.头插节点 6.头删节点 7.寻找pos位置的节点 8.在pos位置之 ...
- 双向带头循环链表-实现思路+图解
目录 一.何为双向循环链表? 1.何为'双向'? 2.何为'带头'? 3.何为'循环'? 二.如何实现双向带头循环链表? 1.基本结构-结点的创建 2.创建哨兵位结点 3.链表的增删查改 一.何为双向 ...
- 双向带头循环链表的(增删查改)的实现
文章目录 一.双向带头循环链表 构成 二.双向带头循环链表的实现 1.函数的定义和结构体的创建--list.h 2.函数的调用--list.c 3. 双向带头循环链表与单链表的传递参数区别 4.双向带 ...
最新文章
- 为什么要开发抽象编程语言(APL)?
- 计算几何-经典算法-凸包
- 论文笔记 Hierarchical Reinforcement Learning for Scarce Medical Resource Allocation
- 【收藏】IntelliJ Idea中配置JavaFX Scene Builder
- 关于Direct2D
- Mac 登陆 去掉 其他用户
- 算法训练 瓷砖铺放 递归
- 【实践】58同城本地服务推荐系统演进
- [20180503]珅与分隔符.txt
- 文字处理控件功能比较:TX Text Control vs. RichTextBox
- 调用css样式是不调用某个属性,CSS选择器可以引用另一个选择器属性吗?
- 3lcd和dlp怎么选,DLP和3LCD投影机的选择对比
- 推荐几个最好用的CRM软件,本人亲测
- 单元测试引入hsqldb探索
- Lync部署之Lync Mobile服务器端的外网设置
- C++基础数论—————容斥原理
- 禁止搜索引擎收录的方法
- MPU6050原始数据分析——学习笔记
- 4.8 期货每日早盘操作建议
- Python词云实现