实现带头双向循环链表
🌈带头双向循环链表
描述:一个节点内包含两个指针,一个指向上一个节点,另一个指向下一个节点。哨兵位指向的下一个节点为头节点,哨兵位的上一个指向尾节点。
结构优势:高效率找尾节点;高效率插入与删除;无需判断多种复杂情况,如尾节点、空节点等。
🌈实现带头双向循环链表
☀️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代理:构建安全通…...

vue左侧漏斗切换 echart图表动态更新
这个需求是根据点击左侧的箭头部分,右侧图表切换,左侧选中数据高亮(图片用的svg) 一、效果图 二、vue组件 <template><div class"funnel_wrap"><div class"flex_between"><div class&q…...

Centos7安装ZK-UI管理界面安装|Maven|Git|
一: JDK1.8安装 参考: Centos7卸载|安装JDK1.8|Xshell7批量控制多个终端 二:Maven安装 2.1:下载maven安装包 maven 下载地址:https://mirror.bit.edu.cn/apache/maven/maven-3/ [rootwww ~]# mkdir -p /usr/local/maven [rootwww ~]# …...

C语言日常刷题7
文章目录 题目答案与解析1234567 题目 1、如下程序的运行结果是( ) char c[5]{a, b, \0, c, \0}; printf("%s", c)A: ‘a’ ‘b’ B: ab\0c\0 C: ab c D: ab 2、若有定义: int a[2][3]; ,以下选项中对 a 数组元素正确…...

037 - 有关时间和日期的函数方法
文档:MySQL :: MySQL 5.7 Reference Manual :: 12.7 Date and Time Functions 以下为案例,更多内容可查看文档 返回当前日期: CURDATE() 返回当前时间: CURTIME() 返回当前日期和时间: NOW() 返回年份&a…...

(JAVA)树——tree
...

js判断对象是否为空对象的方法总结
js判断对象是否为空对象的方法总结 方法1:JSON.stringify()方法方法2:for in方法方法3:Object.keys()方法方法4:Object.getOwnPropertyNames()方法方法5:jquery 的 isEmptyObject()方法 在面试或者开发过程中ÿ…...

LeetCode1049. 最后一块石头的重量 II
1049. 最后一块石头的重量 II 文章目录 [1049. 最后一块石头的重量 II](https://leetcode.cn/problems/last-stone-weight-ii/)一、题目二、题解方法一:01背包二维数组算法思路具体实现 方法二:01背包一维数组 一、题目 有一堆石头,用整数数…...

universal robot 机械臂 官方基本教程
https://academy.universal-robots.cn/modules/e-Series-core-track/Chinese/module3/story_html5.html?courseId2166&languageChinese 教程1 控制箱内部 包含: 主机板,SD卡,和安全控制板 安全控制板负责所有控制信息,包括…...

网络常见安全漏洞
引言 随着互联网的迅猛发展,网络安全问题日益严重。在网络世界中,各种常见的安全漏洞给人们的通信和数据安全带来了巨大的威胁。本文将介绍一些常见的网络安全漏洞,并提供一些防范措施。 1. XSS(跨站脚本攻击) 跨站…...

【JS案例】JS实现图片放大镜功能
JS案例图片放大镜 🌟效果展示 🌟HTML结构 🌟CSS样式 🌟实现思路 🌟具体实现 1.初始化数据图片 2.获取所需DOM元素 3.初始化页面 初始化缩略图 绑定事件 🌟完整代码 🌟写在最后 &…...