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

双向链表专题

链表的分类:

链表的结构非常多样,以下情况组合起来就有8种(2 x 2 x 2)链表结构:
带头:指的是链表中有哨兵位节点,该哨兵位节点即头节点

1. 双向链表的结构

注意:这⾥的“带头”跟前面我们说的“头节点”是两个概念,实际前面的在单链表阶段称呼不严
谨,但是为了同学们更好的理解就直接称为单链表的头节点。
带头链表面的头节点,实际为“哨兵位”,哨兵位节点不存储任何有效元素,只是站在这里“放哨
的”。
“哨兵位”存在的意义:
遍历循环链表避免死循环。

2. 双向链表的实现

1 typedef int LTDataType;
2 typedef struct ListNode
3 {
4 struct ListNode* next; //指针保存下⼀个节点的地址
5 struct ListNode* prev; //指针保存前⼀个节点的地址
6 LTDataType data;
7 }LTNode;
8 //void LTInit(LTNode** pphead);
9 LTNode* LTInit();
10 void LTDestroy(LTNode* phead);
11 void LTPrint(LTNode* phead);
12 bool LTEmpty(LTNode* phead);
13 void LTPushBack(LTNode* phead, LTDataType x);
14 void LTPopBack(LTNode* phead);
15 void LTPushFront(LTNode* phead, LTDataType x);
16 void LTPopFront(LTNode* phead);
17 //在pos位置之后插⼊数据
18 void LTInsert(LTNode* pos, LTDataType x);
19 void LTErase(LTNode* pos);
20 LTNode *LTFind(LTNode* phead,LTDataType x);
#define _CRT_SECURE_NO_WARNINGS
#include"list.h"
void LTPrint(LTNode* phead)
{LTNode* pcur = phead->next;while (pcur != phead){printf("%d->", pcur->data);pcur = pcur->next;}printf("\n");
}
//申请节点
LTNode* LTBuyNode(LTDataType x)
{LTNode* node = (LTNode*)malloc(sizeof(LTNode));if (node == NULL){perror("malloc fail");exit(1);}node->data = x;node->next = node->prev = node;return node;
}
//初始化
//void LTInit(LTNode** pphead)
//{
//	//给双向链表创建一个哨兵位
//	*pphead = LTBuyNode(-1);
//
//}
LTNode* LTInit()
{LTNode* phead = LTBuyNode(-1);return phead;
}
//尾插
void LTPushBack(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = LTBuyNode(x);//phead phead->prev newnodenewnode->prev = phead->prev;newnode->next = phead;phead->prev->next = newnode;phead->prev = newnode;
}
//头插
void LTPushFront(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = LTBuyNode(x);newnode->prev = phead;newnode->next = phead->next;phead->next->prev = newnode;phead->next = newnode;
}
//尾删
void LTPopBack(LTNode* phead, LTDataType x)
{//链表必须有效且不能为空assert(phead && phead->next != phead);LTNode* del = phead->prev;del->prev->next = phead;phead->prev = del->prev;//删除delfree(del);del = NULL;}
//头删
void LTPopFront(LTNode* phead, LTDataType x)
{assert(phead && phead->next != phead);LTNode* del = phead->next;phead->next = del->next;del->next->prev = phead;//删除delfree(del);del = NULL;
}
LTNode* LTFind(LTNode* phead, LTDataType x)
{LTNode* pcur = phead->next;while (pcur != phead){if (pcur->data == x){return pcur;}pcur = pcur->next;}//没找到return NULL;
}
//在pos位置之后插入数据
void LTInsert(LTNode* pos, LTDataType x)
{assert(pos);LTNode* newnode = LTBuyNode(x);newnode->next = pos->next;newnode->prev = pos;pos->next->prev = newnode;pos->next = newnode;
}
//删除pos节点
void LTErase(LTNode* pos)
{//pos理论上来说不能为phead,但是没有参数phead,无法增加校验assert(pos);pos->next->prev = pos->prev;pos->prev->next = pos->next;free(pos);pos = NULL;
}
//销毁链表
void LTDesTroy(LTNode* phead)
{assert(phead);LTNode* pcur = phead->next;while (pcur != phead){LTNode* next = pcur->next;free(pcur);pcur = next;}//此时pcur指向pheadfree(phead);phead = NULL;
}

3. 顺序表和双向链表的优缺点分析

不同点顺序表链表(单链表)
存储空间上物理上一定连续逻辑上连续,但物理上不一定连续
随机访问支持O(1)不支持:O(n)
任意位置插入或者删除元素可能需要搬移元素只需要修改指针指向
插入动态顺序表没有容量的概念
应用场景元素高效存储+频繁访问任意位置插入和频繁删除

http://www.xdnf.cn/news/5697.html

相关文章:

  • 51 单片机头文件 reg51.h 和 reg52.h 详解
  • element plus el-table多选框跨页多选保留
  • 2-巯基烟酰甘氨酸 晒后美白新配方,解决皮肤暗沉
  • M8040A/M8199助力数据中心收发信机测试
  • 树莓派开发环境部署(任何类型的树莓派),最简易
  • 新书速览|纯血鸿蒙HarmonyOS NEXT原生开发之旅
  • 使用conda导致无法找到libpython动态库
  • 【番外】01:Windows 安装配置 CUDA 和 cuDNN 教程
  • 【RTOS】 vxworks里面的配置项
  • vscode 默认环境路径
  • cursor 30.Our servers are currently........
  • 1.2 函数
  • SpringBoot医院病房信息管理系统开发实现​
  • 【HTOP 使用指南】:如何理解主从线程?(以 Faster-LIO 为例)
  • 嵌入式软件--stm32 DAY 6 USART串口通讯(下)
  • 从逻辑学视角探索数学在数据科学中的系统应用:一个整合框架
  • 1.3 极限
  • Java线程的优先级(Priority)
  • nginx配置sse流传输问题:直到所有内容返回后才往下传输
  • 1.7 方向导数
  • TiDB预研-基本模块、初步使用
  • [笔记]几起风电结构失效案例
  • 踩坑记录-恒源云-GPUSHARE
  • 大小端的判断方法
  • Spring Cache的详细使用
  • 编程技能:字符串函数03,strncpy
  • 碰一碰发视频源码搭建,支持OEM
  • 解决在 PowerShell 中 `javac -version` 命令无法运行
  • Qwen:Qwen3,R1 在 Text2SQL 效果评估
  • 1.5 连续性与导数