循环链表 -- c语言实现
#pragma once
// 带头+双向+循环链表增删查改实现
#include<stdlib.h>
#include<stdio.h>
#include<assert.h>typedef int LTDataType;typedef struct ListNode
{LTDataType data;struct ListNode* next;struct ListNode* prev;
}ListNode;//双链表申请一个新节点
ListNode* BuyListNode(LTDataType x);// 创建返回链表的头结点
ListNode* ListCreate();// 双向链表打印
void ListPrint(ListNode* pHead);// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x);// 双向链表尾删
void ListPopBack(ListNode* pHead);// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x);// 双向链表头删
void ListPopFront(ListNode* pHead);// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x);// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);// 双向链表删除pos位置的节点
void ListErase(ListNode* pos);// 双向链表销毁
void ListDestory(ListNode* pHead);//双链表申请一个新节点
ListNode* BuyListNode(LTDataType x)
{ListNode* node = (ListNode*)malloc(sizeof(ListNode));if (node == NULL){perror("BuyListNode::malloc");return NULL;}node->data = x;node->next = NULL;node->prev = NULL;return node;
}// 创建返回链表的头结点
ListNode* ListCreate()
{ListNode* head = BuyListNode(-1);head->next = head;head->prev = head;
}// 双向链表打印
void ListPrint(ListNode* pHead)
{assert(pHead);ListNode* cur = pHead->next;printf("head<=>");while (cur != pHead){printf("%d<=>", cur->data);cur = cur->next;}printf("\n");return;
}// 双向链表尾插
// void ListPushBack(ListNode* pHead, LTDataType x)
// {
// assert(pHead);
// ListNode* newnode = BuyListNode(x);
// ListNode* tail = pHead->prev;
// tail->next = newnode;
// newnode->prev = tail;
// newnode->next = pHead;
// pHead->prev = newnode;
// return;
// }
// 下面的写法更容易理解
void ListPushBack(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* newnode = BuyListNode(x);newnode->next = pHead;newnode->prev = pHead->prev;pHead->prev->next = newnode;pHead->prev = newnode;return;}// 双向链表尾删
void ListPopBack(ListNode* pHead)
{assert(pHead);ListNode* tail = pHead->prev;if (tail == pHead)return;tail->prev->next = pHead;pHead->prev = tail->prev;free(tail);tail = NULL;return;
}// 双向链表头插
// void ListPushFront(ListNode* pHead, LTDataType x)
// {
// assert(pHead);
// ListNode* newnode = BuyListNode(x);
// newnode->next = pHead->next;
// pHead->next->prev = newnode;
// pHead->next = newnode;
// newnode->prev = pHead;
// return;
// }void ListPushFront(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* newnode = BuyListNode(x);newnode->next = pHead->next;newnode->prev = pHead;pHead->next->prev = newnode;pHead->next = newnode;return;
}// 双向链表头删
void ListPopFront(ListNode* pHead)
{assert(pHead);ListNode* tmp = pHead->next;if (tmp == pHead)return;tmp->next->prev = pHead;pHead->next = tmp->next;free(tmp);tmp = NULL;
}// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* cur = pHead;while (cur->data != x){cur = cur->next;if (cur == pHead)return NULL;}return cur;
}// 双向链表在pos的前面进行插入
// void ListInsert(ListNode* pos, LTDataType x)
// {
// assert(pos);
// ListNode* newnode = BuyListNode(x);
// pos->prev->next = newnode;
// newnode->prev = pos->prev;
// pos->prev = newnode;
// newnode->next = pos;
// return;
// }
// 下面这个更好理解,且避免了pos为头节点时若头节点的 next 为 NULL 时的错误
void ListInsert(ListNode* pos, LTDataType x)
{assert(pos);ListNode* newnode = BuyListNode(x);newnode->next = pos;newnode->prev = pos->prev;pos->prev->next = newnode;pos->prev = newnode;return;
}// 双向链表删除pos位置的节点
void ListErase(ListNode* pos)
{assert(pos);pos->prev->next = pos->next;pos->next->prev = pos->prev;free(pos);pos = NULL;return;
}// 双向链表销毁
void ListDestory(ListNode* pHead)
{assert(pHead);ListNode* cur = pHead->next;while (cur != pHead){ListNode* tmp = cur->next;free(cur);cur = tmp;}free(pHead);return;
}int main() {// 创建一个双向循环链表,头节点headListNode* myList = ListCreate();// 尾插元素ListPushBack(myList, 1);ListPushBack(myList, 2);ListPushBack(myList, 3);// 头插元素ListPushFront(myList, 0);// 打印链表ListPrint(myList); // 应该输出:head<=>0<=>1<=>2<=>3<=>// 查找元素ListNode* foundNode = ListFind(myList, 2);if (foundNode != NULL) {printf("找到的节点的data: %d\n", foundNode->data); // 应该输出:Found node with value: 2} else {printf("没有找到\n");}// 在指定位置前插入元素ListInsert(foundNode, 10);// 打印链表ListPrint(myList); // 应该输出:head<=>0<=>1<=>10<=>2<=>3<=>// 删除指定位置的元素ListErase(foundNode);// 打印链表ListPrint(myList); // 应该输出:head<=>0<=>1<=>10<=>3<=>// 头删元素ListPopFront(myList);// 尾删元素ListPopBack(myList);// 打印链表ListPrint(myList); // 应该输出:head<=>1<=>2<=>// 打印 head 的 prev 的 dataprintf("head->prev->data: %d", myList->prev->data);// 销毁链表ListDestory(myList);return 0;
}
运行结果:
相关文章:

循环链表 -- c语言实现
#pragma once // 带头双向循环链表增删查改实现 #include<stdlib.h> #include<stdio.h> #include<assert.h>typedef int LTDataType;typedef struct ListNode {LTDataType data;struct ListNode* next;struct ListNode* prev; }ListNode;//双链表申请一个新节…...

如何使git提交的时候忽略一些特殊文件?
认识.gitignore文件 在生成远程仓库的时候我们会看到这样一个选项: 这个.gitignore文件有啥用呢? .gotignore文件是Git版本控制系统中的一个特殊文件。用来指定哪些文件或者目录不被Git追踪或者提交到版本库中。也就意味着,如果我们有一些文…...

如何保证Redis双写一致性?
目录 数据不一致问题 数据库和缓存不一致解决方案 1. 先更新缓存,再更新数据 该方案数据不一致的原因 2. 先更新数据库,再更新缓存 3. 先删除缓存,再更新数据库 延时双删 4. 先更新数据库,再删除缓存 该方案数据不一致的…...

HarmonyOS实战开发-如何实现查询当前城市实时天气功能
先来看一下效果 本项目界面搭建基于ArkUI中TS扩展的声明式开发范式, 数据接口是和风(天气预报), 使用ArkUI自带的网络请求调用接口。 我想要实现的一个功能是,查询当前城市的实时天气, 目前已实现的功能…...

(三)JSP教程——JSP动作标签
JSP动作标签 用户可以使用JSP动作标签向当前输出流输出数据,进行页面定向,也可以通过动作标签使用、修改和创建对象。 <jsp:include>标签 <jsp:include>标签将同一个Web应用中静态或动态资源包含到当前页面中。资源可以是HTML、JSP页面和文…...

centos7安装真的Redmine-5.1.2+ruby-3.0.0
下载redmine-5.1.2.tar.gz,上传到/usr/local/目录下 cd /usr/local/ tar -zxf redmine-5.1.2.tar.gz cd redmine-5.1.2 cp config/database.yml.example config/database.yml 配置数据连接 #编辑配置文件 vi config/database.yml #修改后的内容如下 product…...

方法的重写
方法的重写 概念:子类继承父类之后,就拥有了符合权限的父类的属性和方法,但是当父类的方法不符合子类的要求的时候,子类也可以重新的书写自己想要的方法。所以,方法的重写,即子类继承父类的方法后…...
Terraform局部值
Terraform输入变量用于从外部传递值到Terraform模块内部进行使用,如果把Terraform代码看作是一个函数的话,Terraform输入变量就是函数的输入参数。 Terraform局部值则用于在Terraform模块内部定义反复使用的常量值或表达式,如果把Terraform代…...

vue+element-ui实现横向长箭头,横向线上下可自定义文字(使用after伪元素实现箭头)
项目场景: 需要实现一个长箭头,横向线上下可自定义文字 代码描述 <div><span class"data-model">{{ //上方文字}}</span><el-divider class"q"> </el-divider>//分隔线<span class"data-mod…...

性能监控之prometheus+grafana搭建
前言 Prometheus和Grafana是两个流行的开源工具,用于监控和可视化系统和应用程序的性能指标。它们通常一起使用,提供了强大的监控和数据可视化功能。 Prometheus Prometheus是一种开源的系统监控和警报工具包。它最初由SoundCloud开发,并于…...

25-ESP32-S3 内置的真随机数发生器(RNG)
ESP32-S3 内置的真随机数发生器(RNG)😎 引言 📚 在许多应用中,随机数发生器(RNG)是必不可少的。无论是在密码学🔒、游戏🎮、模拟🧪或其他领域,随…...

万兆以太网MAC设计(12)万兆UDP协议栈上板与主机网卡通信
文章目录 一、设置IP以及MAC二、上板效果2.1、板卡与主机数据回环测试2.2、板卡满带宽发送数据 一、设置IP以及MAC 顶层模块设置源MAC地址 module XC7Z100_Top#(parameter P_SRC_MAC 48h01_02_03_04_05_06,parameter P_DST_MAC 48hff_ff_ff_ff_ff_ff )(input …...

2024年4月17日华为春招实习试题【三题】-题目+题解+在线评测,2024.4.17,华为机试
2024年4月17日华为春招实习试题【三题】-题目题解在线评测 🔮题目一描述:扑克牌消消乐输入描述输出描述样例一样例二Limitation解题思路一:模拟,遇到连续3张相同牌号的卡牌,直接删除解题思路二:栈解题思路三…...

展开说说:Android线程池解析
何谓线程池?本人理解是存放和管理线程的一个容器。 线程池存在的意义是什么? 第一:前面博客提到过创建和销毁线程的操作本身是有性能开销的,如果把使用的线程对象存起来下次用的时候直接取出来用就省去了一次创建和销毁的成本&a…...

Selenium自动化测试面试题全家桶
🔥 交流讨论:欢迎加入我们一起学习! 🔥 资源分享:耗时200小时精选的「软件测试」资料包 🔥 教程推荐:火遍全网的《软件测试》教程 📢欢迎点赞 👍 收藏 ⭐留言 …...
Docker 容器日志占用空间过大解决办法
1、vi /etc/docker/daemon.json {"log-driver":"json-file","log-opts": {"max-size":"200m", "max-file":"1"} } 2、重新加载守护进程配置文件 systemctl daemon-reload 3、重启docker systemctl…...

update_min_vruntime()流程图
linux kernel scheduler cfs的update_min_vruntime() 看起来还挺绕的。含义其实也简单,总一句话,将 cfs_rq->min_vruntime 设置为: max( cfs_rq->vruntime, min(leftmost_se->vruntime, cfs_rq->curr->vruntime) )。 画个流…...
十进制转任意进制(以及任意进制来回转换<了解>)
十进制转任意进制: #include <iostream> #include <vector> #include <string> using namespace std; // 将十进制数转换为P进制形式的字符串 string toBase(int num, int base) {string result ""; // 初始化结果字符串为空wh…...

postcss-px-to-viewport 从入坑到放弃 (nuxt3搭建响应式官网解决方案 )
前沿 什么是 postcss-px-to-viewport 将px单位转换为视口单位的 (vw, vh, vmin, vmax) 的 PostCSS 插件。 为什么使用 postcss-px-to-viewport 在pc端盛行的时代 ,如果你不想去适配更多的pc端代码,可以采用它。 由于nuxt3本身已带postcss,所…...
C语言从入门到入门
一、引言 C语言是一种通用的、过程式的计算机编程语言,支持结构化编程、词汇变量作用域和递归等功能,其设计提供了低级别的存取权限,并且要求程序员管理所有的内存细节。C语言具有高效、灵活和可移植性等特点,因此被广泛应用于系统编程、嵌入式系统开发、游戏开发等领域。 …...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...

深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
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))…...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...

Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...

实战三:开发网页端界面完成黑白视频转为彩色视频
一、需求描述 设计一个简单的视频上色应用,用户可以通过网页界面上传黑白视频,系统会自动将其转换为彩色视频。整个过程对用户来说非常简单直观,不需要了解技术细节。 效果图 二、实现思路 总体思路: 用户通过Gradio界面上…...