当前位置: 首页 > news >正文

双向-->带头-->循环链表

目录

一、双向带头循环链表概述

1.什么是双向带头循环链表

2.双向带头循环链表的优势

3.双向带头循环链表简图

二、双向带头循环链表的增删查改图解及代码实现

1.双向带头循环链表的头插

2.双向带头循环链表的尾插

3.双向带头循环链表的头删

4.双向带头循环链表的尾删

5.双向带头循环链表在pos位置前插入节点

6.双向带头循环链表删除pos位置节点


一、双向带头循环链表概述

1.什么是双向带头循环链表

        双向:每个节点都带有一个指向下一个节点的指针(next)和一个直向前一个节点的指针(prev);

        带头:即链表带有哨兵位头节点,该节点只包含两个指针,不存储有效数据;

        循环:哨兵位头节点有一个next指针指向第一个有效数据节点,还有一个prev指针指向哨兵位节点的前一个节点即链表的尾节点,因此实现了链表的循环;

        双向带头循环链表的节点类型:

typedef int LTDataType;
typedef struct ListNode
{LTDataType data;struct ListNode* next;struct ListNode* prev;
}ListNode;

2.双向带头循环链表的优势

        双向带头循环链表不需要我们遍历每个节点来找尾节点,对于链表的尾插而言就变得非常简单。由于较单向非循环链表而言,双向带头循环链表多了一个指向前一个节点的指针prev,所以在结构上较为复杂,但实际应用中少了很多的麻烦。

3.双向带头循环链表简图

 

二、双向带头循环链表的增删查改图解及代码实现

1.双向带头循环链表的头插

示意图:

代码实现:

// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* NewNode = Node_New(x);ListNode* First = pHead->next;NewNode->next = First;First->prev = NewNode;NewNode->prev = pHead;pHead->next = NewNode;
}

2.双向带头循环链表的尾插

示意图:

代码实现:

// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* NewNode = Node_New(x);ListNode* Tail = pHead->prev;NewNode->prev = Tail;Tail->next = NewNode;NewNode->next = pHead;pHead->prev = NewNode;
}

3.双向带头循环链表的头删

示意图:

代码实现:

// 双向链表头删
void ListPopFront(ListNode* pHead)
{assert(pHead);if (pHead->next == pHead){return;}ListNode* First = pHead->next;ListNode* Next = First->next;pHead->next = Next;Next->prev = pHead;free(First);First = NULL;
}

4.双向带头循环链表的尾删

示意图:

代码实现:

// 双向链表尾删
void ListPopBack(ListNode* pHead)
{assert(pHead);if (pHead->next == pHead){return;}ListNode* Tail = pHead->prev;ListNode* Prev = Tail->prev;Prev->next = pHead;pHead->prev = Prev;free(Tail);Tail = NULL;
}

5.双向带头循环链表在pos位置前插入节点

示意图:

代码实现:

// 双向链表在pos位置的前面插入节点
void ListInsert(ListNode* pos, LTDataType x)
{ListNode* NewNode = Node_New(x);ListNode* Prev = pos->prev;Prev->next = NewNode;NewNode->prev = Prev;NewNode->next = pos;pos->prev = NewNode;
}

6.双向带头循环链表删除pos位置节点

示意图:

代码实现:

// 双向链表删除pos位置的节点
void ListErase(ListNode* pos)
{ListNode* Prev = pos->prev;ListNode* Hind = pos->next;Prev->next = Hind;Hind->prev = Prev;free(pos);pos = NULL;
}

http://www.lryc.cn/news/127972.html

相关文章:

  • Opencv4基于C++基础入门笔记:OpenCV环境配置搭建
  • JS基础之实现map方法
  • FPGA应用学习笔记-----复位电路(二)和小结
  • 信捷 XD PLC 16位整数转换为双精度浮点数
  • (二)结构型模式:1、适配器模式(Adapter Pattern)(C++实现示例)
  • 【编程二三事】ES究竟是个啥?
  • 爬虫逆向实战(三)--天某云登录
  • 不要过于迷恋软件架构,要重视如何设计根据简单和清晰的设计
  • Grafana监控 Redis Cluster
  • k8s 认证和权限控制
  • 性能优化的重要性
  • Leetcode No.53 Maximum Subarray
  • 手机出现 不读卡 / 无信号时应该怎么办?
  • Linux 内核模块运行机制(10/11)
  • MySQL数据库-字符串函数详解
  • 半导体退火那些事(3)
  • 1281. 整数的各位积和之差
  • 如何使用Vue和C++实现OJ《从零开始打造 Online Judge》
  • 在Spring Boot和Vue中实现请求过滤器以验证请求头中的Token
  • ThreeJS——在3D地球上标记中国地图板块
  • 第2章 性能测量
  • 未来,运营的重要性大于产品?
  • paddle ocr框架识别数字问题和解决方案
  • 构建高性能的MongoDB数据迁移工具:Java的开发实践
  • 2023年国赛数学建模思路 - 案例:最短时间生产计划安排
  • 1572. 矩阵对角线元素的和
  • 在vue中使用swiper轮播图(搭配watch和$nextTick())
  • Java书签 #使用MyBatis接入多数据源
  • 神经网络基础-神经网络补充概念-23-神经网络的梯度下降法
  • 鸿蒙3.1 设备管理DeviceManager