实现带头双向循环链表
🌈带头双向循环链表

描述:一个节点内包含两个指针,一个指向上一个节点,另一个指向下一个节点。哨兵位指向的下一个节点为头节点,哨兵位的上一个指向尾节点。
结构优势:高效率找尾节点;高效率插入与删除;无需判断多种复杂情况,如尾节点、空节点等。
🌈实现带头双向循环链表
☀️list.h
#define _CRT_SECURE_NO_WARNINGS
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int DataType;
typedef struct ListNode {struct ListNode* prev;struct ListNode* next;DataType data;
}ListNode;ListNode* BuyListNode(DataType x);
ListNode* InitList();
void DestroyList(ListNode* phead);void Print(ListNode* phead);
int CountSize(ListNode* phead);void PushBack1(ListNode* phead, DataType x);
void PushBack2(ListNode* phead, DataType x);void PopBack1(ListNode* phead);
void PopBack2(ListNode* phead);void PushFront1(ListNode* phead, DataType x);
void PushFront2(ListNode* phead, DataType x);void PopFront1(ListNode* phead);
void PopFront2(ListNode* phead);void Insert(ListNode* pos, DataType x);
void Erase(ListNode* pos);
☀️list.c
BuyListNode节点创建函数()
ListNode* BuyListNode(DataType x) {ListNode* node = (ListNode*)malloc(sizeof(ListNode));if (node == NULL) {perror("malloc fail");exit(-1);}node->data = x;node->prev = NULL;node->next = NULL;return node;
}
InitList链表初始化函数()
ListNode* InitList() {ListNode* phead = BuyListNode(0);phead->next = phead;phead->prev = phead;return phead;
}
DestroyList链表销毁函数()
void DestroyList(ListNode* phead) {assert(phead);ListNode* cur = phead->next;while (cur != phead) {ListNode* curnext = cur->next;free(cur);cur = curnext;}free(phead);
}
打印节点信息函数Print()
void Print(ListNode* phead) {assert(phead);printf("phead<=>");ListNode* cur = phead->next;while (cur != phead) {printf("%d<=>", cur->data);cur = cur->next;}printf("\n");
}
统计节点个数函数CountSize()
int CountSize(ListNode* phead) {assert(phead);int size = 0;ListNode* cur = phead->next;while (cur != phead) {size++;cur = cur->next;}return size;
}
在pos位置节点前插入函数Insert()
//在pos前插入
void Insert(ListNode* pos, DataType x) {assert(pos);ListNode* posprev = pos->prev;ListNode* newnode = BuyListNode(x);posprev->next = newnode;newnode->prev = posprev;newnode->next = pos;pos->prev = newnode;
}
删除pos位置节点函数Erase()
void Erase(ListNode* pos) {assert(pos);ListNode* posprev = pos->prev;ListNode* posnext = pos->next;free(pos);posprev->next = posnext;posnext->prev = posprev;
}
尾插(两种方法)PushBack1()&PushBack2()
void PushBack1(ListNode* phead, DataType x) {ListNode* tail = phead->prev;ListNode* newnode = BuyListNode(x);newnode->next = phead;phead->prev = newnode;tail->next = newnode;newnode->prev = tail;
}
void PushBack2(ListNode* phead, DataType x) {//尾插就相当于在哨兵位head前插入Insert(phead, x);
}
尾删(两种方法)PopBack1()&PopBack2()
void PopBack1(ListNode* phead) {assert(phead);assert(phead->next != phead);ListNode* tail = phead->prev;ListNode* tailprev = tail->prev;free(tail);tailprev->next = phead;phead->prev = tailprev;
}
void PopBack2(ListNode* phead) {//尾节点就是phead的prev节点Erase(phead->prev);
}
头插(两种方法)PushFront1()&PushFront2()
void PushFront1(ListNode* phead, DataType x) {assert(phead);ListNode* newnode = BuyListNode(x);ListNode* pheadnext = phead->next;newnode->next = pheadnext;pheadnext->prev = newnode;phead->next = newnode;newnode->prev = phead;
}
void PushFront2(ListNode* phead, DataType x) {//头插就相当于在phead后一个节点的前面插入assert(phead);Insert(phead->next, x);
}
头删(两种方法)PopFront1()&PopFront2()
void PopFront1(ListNode* phead) {assert(phead);assert(phead->next != phead);ListNode* first = phead->next;ListNode* second = first->next;free(first);phead->next = second;second->prev = phead;
}
void PopFront2(ListNode* phead) {//头节点时哨兵位phead的下一个节点Erase(phead->next);
}
☀️测试
测试尾插:test_PushBack(()
#define _CRT_SECURE_NO_WARNINGS
#include"list.h"
void test_PushBack() {ListNode* plist = InitList();PushBack1(plist, 1);PushBack1(plist, 2);PushBack1(plist, 3);PushBack2(plist, 1);PushBack2(plist, 2);PushBack2(plist, 3);Print(plist);DestroyList(plist);
}
测试结果:

测试尾删:test_PopBack()
void test_PopBack() {ListNode* plist = InitList();PushBack1(plist, 1);PushBack1(plist, 2);PushBack1(plist, 3);PushBack2(plist, 1);PushBack2(plist, 2);PushBack2(plist, 3);Print(plist);PopBack1(plist);Print(plist);PopBack2(plist);Print(plist);DestroyList(plist);
}
测试结果:

测试头插:test_PushFront()
void test_PushFront() {ListNode* plist = InitList();PushFront1(plist, 1);PushFront1(plist, 2);PushFront1(plist, 3);PushFront2(plist, 1);PushFront2(plist, 2);PushFront2(plist, 3);Print(plist);DestroyList(plist);
}
测试结果:

测试头删:test_PopFront()
void test_PopFront() {ListNode* plist = InitList();PushFront1(plist, 1);PushFront1(plist, 2);PushFront1(plist, 3);PushFront2(plist, 1);PushFront2(plist, 2);PushFront2(plist, 3);Print(plist);PopFront1(plist);Print(plist);PopFront2(plist);Print(plist);DestroyList(plist);
}
测试结果:

测试用主函数
int main() {//测试尾插test_PushBack();//测试尾删test_PopBack();//测试头插test_PushFront();//测试头删test_PopFront();
}相关文章:
实现带头双向循环链表
🌈带头双向循环链表 描述:一个节点内包含两个指针,一个指向上一个节点,另一个指向下一个节点。哨兵位指向的下一个节点为头节点,哨兵位的上一个指向尾节点。 结构优势:高效率找尾节点;高效率插入…...
Mysql 表字符集变更
背景 线上有几张表的字符集是 latin1,要求换成utf8mb4。至于操作的时机则需要自行判断。 1.查看库中所有字符集为latin1的所有表 SELECTDISTINCTtable_schema,table_name,collation_name,character_set_name,CONCAT(ALTER TABLE , table_schema, ., table_name, …...
golang抓取tcp包的实现
要抓取 TCP 请求的数据包,你可以使用 golang 中的 packet 库和 pcap 库。下面是一种使用这些库来抓取 TCP 数据包的方法: 首先,确保已经安装了 pcap 库,可以使用以下命令来安装: go get -u github.com/google/gopack…...
oauth2.0第2季 分布式认证与授权实现单点登录
一 oauth介绍 1.0 疑问汇总 1.使用jwttoken进行令牌传输,资源服务器在本地怎么验证token? 1.1 oauth的基础内容 1.1.1 oauth是什么 1.1.2 oauth的角色 1.1.3 oauth的认证流程 1.1.4 oauth的4种模式 1.2 为何要用oauth2.0 1.介绍单体架构 使用ses…...
SpringBoot一些困惑及梳理
Spring中常用的classpath前缀到底指向哪里? classpath实际就是和java命令行运行时指定的classpath是同一个概念,在ideamaven中也就是指向target/classes目录。不要被网上哪些复制粘贴的文章所迷惑。classpath: 和 classpath*: 到底什么区别? classpath: 实际就是当…...
PostgreSQL汉字转拼音首字母
PostgreSQL汉字转拼音首字母,最近有个需求要做搜索优化,要求提取汉字首字母识别输入,图方便直接数据库用函数批量转换了,整理了网上的两个方法函数备忘,非原创。 https://blog.qdac.cc/?p1281 https://developer.aliy…...
HBuilderX修改manifest.json设置,解决跨域问题(CORS、Cross-Origin)
搭建一个前台uniapp,后台springboot的开发环境时,遇到了跨域问题。 console提示错误信息: Access to XMLHttpRequest at http://10.0.180.203/api/cms/getAdList?apId1 from origin http://localhost:8080 has been blocked by CORS policy…...
AR地图微信小程序:数字化时代下地图应用的新突破
随着数字化时代的到来,地图应用成为人们日常生活中不可或缺的工具。而随着增强现实(AR)技术的快速发展,AR地图微信小程序应运而生,为用户提供了一种全新的地图导航体验。本文将深入探讨AR地图微信小程序的专业性和思考…...
成集云 | 抖店客户静默下单催付数据同步钉钉 | 解决方案
源系统成集云目标系统 方案介绍 随着各品牌全渠道铺货,主播在平台上直播时客户下了订单后不能及时付款,第一时间客户收不到提醒,不仅造成了客户付款率下降,更大量消耗了企业的人力成本和经济。而成集云与钉钉深度合作࿰…...
C++中的运算符总结(5):按位逻辑运算符
C中的运算符总结(5):按位逻辑运算符 9、按位运算符 NOT( ~)、 AND( &)、 OR( |)和 XOR( ^) 逻辑运算符和按位运算符之前的差别在…...
《异常检测——从经典算法到深度学习》22 Kontrast: 通过自监督对比学习识别软件变更中的错误
《异常检测——从经典算法到深度学习》 0 概论1 基于隔离森林的异常检测算法 2 基于LOF的异常检测算法3 基于One-Class SVM的异常检测算法4 基于高斯概率密度异常检测算法5 Opprentice——异常检测经典算法最终篇6 基于重构概率的 VAE 异常检测7 基于条件VAE异常检测8 Donut: …...
大数据风控介绍
众所周知,金融是数据化程度最高的行业之一,也是人工智能和大数据技术重要的应用领域。随着大数据收集、存储、分析和模型技术日益成熟,大数据技术逐渐应用到金融风控的各个环节。个推作为专业的数据智能服务商,拥有海量数据资源&a…...
Linux内核学习(九)—— 虚拟文件系统(基于Linux 2.6内核)
虚拟文件系统(VFS)作为内核子系统,为用户空间程序提供了文件和文件系统相关的接口。通过虚拟文件系统,程序可以利用标准的 Unix 系统调用对不同的文件系统(甚至不同介质上的文件系统)进行读写操作。 一、通…...
【模拟】算法实战
文章目录 一、算法原理二、算法实战1. leetcode1576 替换所有的问号2. leetcode495 提莫攻击3. leetcode6 N字形变换4. leetcode38 外观数列5. leetcode1419 数青蛙 三、总结 一、算法原理 模拟就是用计算机来模拟题目中要求的操作,模拟题目通常具有代码量大、操作…...
各个微服务模块之间互相依赖调用的问题
首先是模块之间不能够循环引用,否则会报循环依赖引入的错误。 没有了模块之间的相互依赖,在项目中这两个模块是相互调用的,分别各自定义相应的Feign接口,如下: 最开始写的运行报错的代码如下: FeignCli…...
理论转换实践之keepalived+nginx实现HA
背景: keepalivednginx实现ha是网站和应用服务器常用的方法,之前项目中单独用nginx实现过负载均衡和服务转发,keepalived一直停留在理论节点,加之最近工作编写的一个技术文档用到keepalived,于是便有了下文。 服务组件…...
华为OD七日集训第1期复盘 - 按算法分类,由易到难,循序渐进,玩转OD(文末送书)
目录 一、活动内容如下第1天、逻辑分析第2天、字符串处理第3天、数据结构第4天、双指针第5天、递归回溯第6天、二分查找第7天、贪心算法 && 二叉树 二、可观测性工程1、简介2、主要内容 大家好,我是哪吒。 最近一直在刷华为OD机试的算法题,坚持…...
MPI之持久化通信句柄与非持久化通信句柄
MPI_Isend & MPI_Send 创建临时通信句柄 在前面的文章中举了例子,我们使用MPI_Isend接口发送数据时,有个传出参数request,该参数是创建的通信句柄, 实际上该句柄是一个临时句柄,即只用于一次性发送数据的场景&…...
搭建个人备忘录中心服务memos、轻量级笔记服务
目录 一、源码 二、官网 三、搭建 四、使用 一、源码 GitHub - usememos/memos: A privacy-first, lightweight note-taking service. Easily capture and share your great thoughts. 二、官网 memos - Easily capture and share your great thoughts 三、搭建 docke…...
探究代理技术在网络安全、爬虫与HTTP通信中的多重应用
在当今高度互联的世界中,代理技术在网络安全、爬虫开发以及HTTP通信中扮演着举足轻重的角色。本文将深入探讨Socks5代理、IP代理以及HTTP代理在这些领域中的多重应用,探索其如何为我们创造更安全、高效的网络环境。 1. Socks5代理:构建安全通…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
sqlserver 根据指定字符 解析拼接字符串
DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...
【笔记】WSL 中 Rust 安装与测试完整记录
#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统:Ubuntu 24.04 LTS (WSL2)架构:x86_64 (GNU/Linux)Rust 版本:rustc 1.87.0 (2025-05-09)Cargo 版本:cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...
