带头双向循环链表

简介: 带头双向循环链表

概述


带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了,后面我们代码实现了就知道了。


双向循环链表含有一个头节点(哨兵位),含有两个指针域,next,prev,分别指向节点的后继和前驱。需要注意的是,头节点的prev指向尾节点,尾节点的next指向头节点

看着复杂,实际操作起来很简单。


初始化


和单链表初始化差不多,无非就是多了一个prev指针

LTNode* CreateLTNode(LTDataType x)
{
  LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
  if (newnode == NULL)
  {
    perror("malloc fail");
    exit(-1);
  }
  newnode->val = x;
  newnode->next = NULL;
  newnode->prev = NULL;
  return newnode;
}
LTNode* LTInit()
{
  LTNode* phead = CreateLTNode(-1);
  phead->next = phead;
  phead->prev = phead;
  return phead;
}


销毁


遍历链表,并定义一个next 来保存 cur 的下一个节点,在链表都free 完后,再销毁头节点;

注意:应该是从头节点的 next 开始遍历。

void ListNodedestroy(LNode* phead)
{
  assert(phead);
  LNode* cur = phead->next;
  while (cur != phead)
  {
    LNode* next = cur->next;
    free(cur);
    cur = next;
  }
  free(phead);
  phead = NULL;
}


插入


找到 pos 的前驱 prev ;

将前驱,pos,新节点链接起来。

void LTInsert(LTNode* pos, LTDataType x)
{
  assert(pos);
  LTNode* posPrev = pos->prev;
  LTNode* newnode = CreateLTNode(x);
  // posprev newnode pos
  posPrev->next = newnode;
  newnode->prev = posPrev;
  newnode->next = pos;
  pos->prev = newnode;
}


删除


找到 pos 的前驱和后继;

链接其前驱,后继;

删除pos。

void LTErase(LTNode* pos)
{
  assert(pos);
  LTNode* posNext = pos->next;
  LTNode* posPrev = pos->prev;
  posPrev->next = posNext;
  posNext->prev = posPrev;
  free(pos);
  //pos = NULL;
}


遍历打印


void LTPrint(LTNode* phead)
{
  assert(phead);
  printf("哨兵位<=>");
  LTNode* cur = phead->next;
  while (cur != phead)
  {
    printf("%d<=>", cur->val);
    cur = cur->next;
  }
  printf("\n");
}
目录
相关文章
|
开发框架 前端开发 .NET
C#编程与Web开发
【4月更文挑战第21天】本文探讨了C#在Web开发中的应用,包括使用ASP.NET框架、MVC模式、Web API和Entity Framework。C#作为.NET框架的主要语言,结合这些工具,能创建动态、高效的Web应用。实际案例涉及企业级应用、电子商务和社交媒体平台。尽管面临竞争和挑战,但C#在Web开发领域的前景将持续拓展。
477 3
|
Web App开发 资源调度 JavaScript
vue element plus 安装
vue element plus 安装
344 0
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的社区智慧养老监护管理平台的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的社区智慧养老监护管理平台的详细设计和实现(源码+lw+部署文档+讲解等)
232 4
|
应用服务中间件 测试技术 nginx
金丝雀发布(灰度发布)介绍 及 声明式管理方法简介
金丝雀发布(灰度发布)介绍 及 声明式管理方法简介
|
11月前
|
存储 监控 Linux
以 CentOS 7 为例,详细介绍了如何对未使用的硬盘进行分区、格式化和挂载的最佳实践
随着业务发展和技术进步,有效管理服务器磁盘空间变得至关重要。本文以 CentOS 7 为例,详细介绍了如何对未使用的硬盘进行分区、格式化和挂载的最佳实践。通过合理规划分区和设置挂载点,可以充分利用磁盘资源,提高系统的稳定性和可维护性。具体步骤包括确认硬盘、创建分区、格式化分区、创建挂载点、临时和永久挂载分区,以及最佳实践建议。
249 3
|
监控 Android开发 开发者
Android经典面试题之实战经验分享:如何简单实现App的前后台监听判断
本文介绍在Android中判断应用前后台状态的两种方法:`ActivityLifecycleCallbacks`和`ProcessLifecycleOwner`。前者提供精细控制,适用于需针对每个Activity处理的场景;后者简化前后台检测,适用于多数应用。两者各有优劣:`ActivityLifecycleCallbacks`更精确但复杂度高;`ProcessLifecycleOwner`更简便但可能在极端场景下略有差异。根据应用需求选择合适方法。
303 2
|
机器学习/深度学习 计算机视觉
【YOLOv10改进-卷积Conv】SCConv :即插即用的空间和通道重建卷积
YOLOv10专栏介绍了将Swin Transformer应用于目标检测的创新。Swin Transformer采用分层窗口结构,解决了视觉任务中的尺度变化问题,提供线性复杂度的效率提升。在图像分类、目标检测和语义分割任务中表现出色,超越先前最佳模型。YOLOv10结合Swin Transformer,利用其局部注意力机制和层次化设计,提升了检测性能。提供的代码片段展示了Swin Transformer模块,包括窗口划分、注意力计算和相对位置偏置。更多信息可在相关博客文章中找到。
|
存储 JSON 安全
[浏览器系列] : 客户端本地存储
[浏览器系列] : 客户端本地存储
177 2
[浏览器系列] : 客户端本地存储
|
机器学习/深度学习 算法 数据挖掘
【机器学习】解释什么是K-means聚类?
【5月更文挑战第11天】【机器学习】解释什么是K-means聚类?