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

  • 链表的分类
  • 实现带有哨兵位的双向的循环链表
    • **定义节点的结构**
    • 初始化单个节点
    • 初始化带有哨兵位的双向循环链表
    • 打印链表
    • 销毁链表
    • 尾插
    • 尾删
    • 头插
    • 头删
    • find函数
    • 在任意位置之前插入
    • 任意位置的删除
    • 全部代码
      • list.h
      • list.c
      • test.c
    • 链表和顺序表的区别

链表的分类

如下
在这里插入图片描述
根据上述的三种组合,一共分为8类

实现带有哨兵位的双向的循环链表

定义节点的结构

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

初始化单个节点

LTNode* BuyListNode(LTDataType x)
{LTNode* newnode=(LTNode*)malloc(sizeof(LTNode));if (newnode==NULL){perror("malloc fail");}newnode->next = NULL;newnode->prev = NULL;newnode->data = x;return newnode;
}

初始化带有哨兵位的双向循环链表

作用:使链表在无数据的情况下就具有循环的特点

LTNode* LTInit()
{LTNode* phead = BuyListNode(-1);phead->next = phead;phead->prev = phead;return phead;
}

打印链表

哨兵位phead一定不能为空,否则无法连接下面的节点

void LTPrint(LTNode* phead)
{assert(phead);printf("<=head=>");LTNode* cur = phead->next;while (cur!=phead){printf("%d<=>",cur->data);cur = cur->next;}printf("\n");
}

销毁链表

void LPDestroy(LTNode* phead)
{assert(phead);LTNode* cur = phead->next;while (cur!=phead){LTNode* next = cur->next;free(cur);cur = next;}free(phead);}

尾插

需要三个节点即可布置好顺序
顺序为:tail newnode phead
在这里插入图片描述

void LTPushBack(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = BuyListNode(x);LTNode* tail = phead->prev;tail->next = newnode;newnode->prev = tail;newnode->next = phead;phead->prev = newnode;}

尾删

增加一个函数用于判断除哨兵位以外是否有其它的节点
bool类型只有两个取值:true和false
需要三个节点,顺序为:tailprev,tail,phead
在这里插入图片描述

bool LTEmpty(LTNode* phead)
{assert(phead);return phead->next == phead;
}void LTPopBack(LTNode* phead)
{assert(phead);assert(!LTEmpty(phead));LTNode* tail = phead->prev;LTNode* tailprev = tail->prev;tailprev->next = phead;phead->prev = tailprev;free(tail);
}

头插

需要三个节点即可布置好顺序
顺序为:phead newnode first

在这里插入图片描述

void LTPushFront(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = BuyListNode(x);LTNode* first = phead->next;newnode->next = first;first->prev = newnode;phead->next = newnode;newnode->prev = phead;
}

头删

增加一个函数用于判断除哨兵位以外是否有其它的节点
bool类型只有两个取值:true和false
需要三个节点,顺序为:phead,tail,tailnex
在这里插入图片描述

void LTPopFront(LTNode* phead)
{assert(phead);assert(!LTEmpty(phead));LTNode* tail = phead->next;LTNode* tailnex = tail->next;phead->next = tailnex;tailnex->prev = phead;free(tail);
}

find函数

从哨兵位的下一个节点开始遍历,直至找到该元素或者遍历到哨兵位结束

LTNode* LTFind(LTNode* phead, LTDataType x)
{assert(phead);LTNode* cur = phead->next;while (cur!=phead){if (cur->data==x){return cur;}cur = cur->next;}return NULL;
}

在任意位置之前插入

任意位置之前的插入需要搭配find函数来使用,需要三个节点,顺序为:posprev,newnode,pos
可以使用它来进行头插和尾插,分别可以表示为LTInsert(phead->next, x) LTInsert(phead, x)
在这里插入图片描述

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

在这里插入图片描述

任意位置的删除

道理同任意位置的插入
在这里插入图片描述

void LTErase(LTNode* pos)
{assert(pos);LTNode* posprev = pos->prev;LTNode* posnex = pos->next;posprev->next = posnex;posnex->prev = posprev;free(pos);
}

结果如下:
在这里插入图片描述

全部代码

list.h

#pragma once
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <stdbool.h>typedef int LTDataType;typedef struct ListNode
{struct ListNode* next;struct ListNode* prev;LTDataType data;
}LTNode;//创建单个的节点
LTNode* BuyListNode(LTDataType x);
//初始化
LTNode* LTInit();
//
void LTPrint(LTNode* phead);
void LPDestroy(LTNode* phead);//尾插
void LTPushBack(LTNode* phead, LTDataType x);
//尾删
void LTPopBack(LTNode* phead);//头插
void LTPushFront(LTNode* phead, LTDataType x);
//头删
void LTPopFront(LTNode* phead);LTNode* LTFind(LTNode* phead, LTDataType x);//任意位置之前的插入
void LTInsert(LTNode* pos, LTDataType x);
//任意位置的删除
void LTErase(LTNode* pos);

list.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "list.h"LTNode* BuyListNode(LTDataType x)
{LTNode* newnode=(LTNode*)malloc(sizeof(LTNode));if (newnode==NULL){perror("malloc fail");}newnode->next = NULL;newnode->prev = NULL;newnode->data = x;return newnode;
}LTNode* LTInit()
{LTNode* phead = BuyListNode(-1);phead->next = phead;phead->prev = phead;return phead;
}void LTPrint(LTNode* phead)
{assert(phead);printf("<=head=>");LTNode* cur = phead->next;while (cur!=phead){printf("%d<=>",cur->data);cur = cur->next;}printf("\n");
}void LPDestroy(LTNode* phead)
{assert(phead);LTNode* cur = phead->next;while (cur!=phead){LTNode* next = cur->next;free(cur);cur = next;}free(phead);}
void LTPushBack(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = BuyListNode(x);LTNode* tail = phead->prev;tail->next = newnode;newnode->prev = tail;newnode->next = phead;phead->prev = newnode;}bool LTEmpty(LTNode* phead)
{assert(phead);return phead->next == phead;
}void LTPopBack(LTNode* phead)
{assert(phead);assert(!LTEmpty(phead));LTNode* tail = phead->prev;LTNode* tailprev = tail->prev;tailprev->next = phead;phead->prev = tailprev;free(tail);
}void LTPushFront(LTNode* phead, LTDataType x)
{assert(phead);LTNode* newnode = BuyListNode(x);LTNode* first = phead->next;newnode->next = first;first->prev = newnode;phead->next = newnode;newnode->prev = phead;
}void LTPopFront(LTNode* phead)
{assert(phead);assert(!LTEmpty(phead));LTNode* tail = phead->next;LTNode* tailnex = tail->next;phead->next = tailnex;tailnex->prev = phead;free(tail);
}LTNode* LTFind(LTNode* phead, LTDataType x)
{assert(phead);LTNode* cur = phead->next;while (cur!=phead){if (cur->data==x){return cur;}cur = cur->next;}return NULL;
}void LTInsert(LTNode* pos, LTDataType x)
{assert(pos);LTNode* newnode= BuyListNode(x);LTNode* posprev = pos->prev;newnode->next = pos;pos->prev = newnode;posprev->next = newnode;newnode->prev = posprev;
}void LTErase(LTNode* pos)
{assert(pos);LTNode* posprev = pos->prev;LTNode* posnex = pos->next;posprev->next = posnex;posnex->prev = posprev;free(pos);
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "list.h"
void Test1()
{LTNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPrint(plist);LTPopBack(plist);LTPopBack(plist);LTPrint(plist);
}void Test2()
{LTNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPushFront(plist, 100);LTPushFront(plist, 200);LTPushFront(plist,300);LTPrint(plist);LTPopFront(plist);LTPrint(plist);}
void Test3()
{LTNode* plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTNode* pos=LTFind(plist, 3);if (pos==NULL){perror("pos NULL");}LTInsert(pos, 100);LTPrint(plist);LTErase(pos);LTPrint(plist);
}
int main()
{//Test1();//Test2();Test3();return 0;
}

链表和顺序表的区别

在这里插入图片描述

局部性原理:加载指定的数据,可能会把与其物理内存之后的数据加载上去。
根据局部性原理,顺序表在载入缓存中时,可能会把与之相邻的数据一同载入,但是,链表的地址并不是相邻的,在载入相应的链表的时候不会把相邻的链表载入缓存。
因此顺序表的缓存利用率比较高。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1801.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一个月学通Python(十八):Django表单的应用(Web开发)

专栏介绍 结合自身经验和内部资料总结的Python教程,每天3章,1个月就能全方位的完成Python的学习并进行实战开发,学完了定能成为大佬!加油吧!卷起来! 全部文章请访问专栏:《Python全栈教程(0基础)》 文章目录 专栏介绍表单的应用表单的应用 我们继续来完成上一章节中…

部署langchain+chatglm

先参考&#xff1a;window零基础部署langchain-ChatGLM_飞奔的屎壳郎的博客-CSDN博客 安装一部分&#xff0c; 1.GCC安装 gcc64位下载 一定要装64位的gcc&#xff0c;因为我的电脑是w10 64位的&#xff0c;装32位运行langchain报错并配置环境变量 可直接用压缩包中的文件&am…

Verilog 学习之路

循环 7-10 代码段 generategenvar i;for (i0; i<8; i i1) begin: my_block_nameassign out[i] in[8-i-1];end endgenerate解释 该代码使用了 S y s t e m V e r i l o g SystemVerilog SystemVerilog 中的 g e n e r a t e generate generate 构造&#xff0c;它允许在…

mysql怎么查询慢查询,及杀死对应进

要查询和处理慢查询&#xff0c;以及杀死对应的进程&#xff0c;可以按照以下步骤进行操作&#xff1a; 1】查询慢查询&#xff1a; 在 MySQL 中&#xff0c;可以通过设置 slow_query_log 参数来启用慢查询日志&#xff0c;并配置 long_query_time 参数设置查询执行时间的阈值…

【软考】系统架构设计风格分类的个人理解

个人适当学习了软考系统架构设计师中关于系统架构设计相关的内容&#xff0c;梳理了一下相关信息。 常见架构类型和常见分类 常见的软考中出现的系统架构列举如下&#xff1a; 分层架构管道-过滤器架构客户端-服务器架构模型-视图-控制器架构&#xff0c;即MVC架构事件驱动架…

行为树(BEHAVIOR TREES)及其工业应用

顾名思义&#xff0c;行为树是描述事物&#xff08;人&#xff0c;动物&#xff0c;机器人&#xff0c;虚拟角色等等&#xff09;行为的树形结构。游戏行业使用行为树为角色行为建模。现在行为树建模技术正在向其它领域渗透&#xff0c;比如工业产线编排&#xff0c;机器人控制…

【从零开始学习C++ | 第二十一篇】C++新增特性 (上)

目录 前言&#xff1a; 委托构造函数&#xff1a; 类内初始化&#xff1a; 空指针&#xff1a; 枚举类&#xff1a; 总结&#xff1a; 前言&#xff1a; C的学习难度大&#xff0c;内容繁多。因此我们要及时掌握C的各种特性&#xff0c;因此我们更新本篇文章&#xff0c;向…

【案例实战】高并发业务的多级缓存架构一致性解决方案

我们在高并发的项目中基本上都离不开缓存&#xff0c;那么既然引入缓存&#xff0c;那就会有一个缓存与数据库数据一致性的问题。 首先&#xff0c;我们先来看看高并发项目里面Redis常见的三种缓存读写模式。 Cache Aside 读写分离模式&#xff0c;是最常见的Redis缓存模式&a…

【状态估计】基于卡尔曼滤波器和扩展卡尔曼滤波器用于 INS/GNSS 导航、目标跟踪和地形参考导航研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

使用Shell制作MySQL自动复制日库月库生成新的日库和月库脚本

日库生成脚本daily.sh #!/bin/bash . /etc/profile . ~/.bash_profile HOSTNAME"127.0.0.1" #数据库信息 PORT"3306" USERNAME"root" PASSWORD"123456" DBNAME"datatest" #要…

【深入探究人工智能】:历史、应用、技术与未来

深入探究人工智能 前言人工智能的历史人工智能的应用人工智能的技术人工智能的未来当代的人工智能产物结语&#x1f340;小结&#x1f340; &#x1f389;博客主页&#xff1a;小智_x0___0x_ &#x1f389;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &am…

LangChain大型语言模型(LLM)应用开发(三):Chains

LangChain是一个基于大语言模型&#xff08;如ChatGPT&#xff09;用于构建端到端语言模型应用的 Python 框架。它提供了一套工具、组件和接口&#xff0c;可简化创建由大型语言模型 (LLM) 和聊天模型提供支持的应用程序的过程。LangChain 可以轻松管理与语言模型的交互&#x…

【UE4 塔防游戏系列】10-防御塔升级

目录 效果 步骤 一、根据防御塔等级修改子弹伤害 二、根据防御塔等级修改子弹速度 三、根据防御塔等级修改检测半径 四、根据防御塔等级修改子弹颜色 五、根据防御塔等级修改换弹时间 效果 步骤 一、根据防御塔等级修改子弹伤害 1. 打开“TowerBaseBullet_Child”&…

现代C++语言核心特征解析——专栏介绍

本专栏用来介绍C新特性&#xff0c;其中包括C11、C14、C17、C20的特性。 下面是C各个版本的出现时间&#xff1a; C版本 时间C112011&#xff5e;2013C142014&#xff5e;2016C172017&#xff5e;2019C202020&#xff5e;2022C232023&#xff5e; 接下来特性更新的顺序不会按…

52 类 110 个常用 Java 组件和框架整理

目录 WEB 容器 数据库 缓存 消息队列 负载均衡 分布式存储 数据库集群 分布式协调 大数据相关 日志收集与分析 搜索 系统监控 分库分表 微服务 RPC 框架 网络框架 MVC 框架 数据层框架 数据库连接池 Redis 客户端 Rest 接口设计与开发 数据参数校验 安全…

【ArcGIS Pro二次开发】(48):三调土地利用现状分类面积汇总统计

之前做了一个三调三大类面积统计&#xff0c;有小伙伴反映太粗糙&#xff0c;想要一个完整的地类面积汇总表。 【ArcGIS Pro二次开发】(35)&#xff1a;三调三大类面积统计 本质上并没有多少难度&#xff0c;之前也做过类似的用地用海汇总表&#xff0c;于是拿出来改一改就好了…

python类中的@classmethod和@staticmethod

classmethod classmethod修饰符对应的函数不需要实例化&#xff0c;无需self参数&#xff0c;但需要cls参数以调用类的属性、类的方法 class A:a 10def printb(self, b):print(b)classmethoddef printa(cls):print(cls.a)print(cls().printb(5))A.printa()"""…

scrapy---爬虫中间件和下载中间件

爬虫中间件 # 爬虫中间件 (了解) middlewares.py class MysfirstscrapySpiderMiddleware:classmethoddef from_crawler(cls, crawler):# This method is used by Scrapy to create your spiders.s cls()crawler.signals.connect(s.spider_opened, signalsignals.spider_opene…

JavaScript的static、this、super关键字介绍

JavaScript的static、this、super关键字介绍 static关键字&#xff1a; ☆ static关键字用于定义类的静态方法和静态属性。 ☆ 静态方法是直接与类相关联的方法&#xff0c;不需要实例化类即可调用。 ☆ 静态属性是类本身的属性&#xff0c;而不是实例的属性。 ☆ 在静态方…

Git学习总结

Git学习 目录 Git学习1.基础1.1 Git Commit:提交记录1.2 Git Branch:创建分支1.3 Git Merge:合并分支的方式一1.4 Git Rebase:合并分支的方式二1.5 查看提交记录&#xff1a;提交历史、详细信息、commit_hash1.6 在提交树上移动 2. 高级2.1 HEAD2.2 相对引用2.3 使用相对引用强…