循环链表 -- c语言实现

news2024/12/27 3:39:45
#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() {
	// 创建一个双向循环链表,头节点head
	ListNode* 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 的 data
    printf("head->prev->data: %d", myList->prev->data);

	// 销毁链表
	ListDestory(myList);

    return 0;
}

运行结果:

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

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

相关文章

【Python】PTA 查验身份

知识点&#xff1a; 1.这里的加权求和就是指每一位乘以题目给的对应位置上的数字 在python中&#xff0c;对于int(10)这样的转换而来的直接是整数10&#xff0c;但是在c语言中会转换成ASCII值&#xff0c;所以要特别注意 2.本题中有两种情况是错误的&#xff0c;就是要直接输…

DES加密解密算法(简单、易懂、超级详细)

目录 一、基础补充 二、什么是DES算法 &#xff08;1&#xff09;对称加密算法 &#xff08;2&#xff09;非对称加密算法 &#xff08;3&#xff09;对称加密算法的应用 三、DES算法的基础操作步骤 1.明文的加密整体过程 2.F轮函数解析 3.密钥的形成过程 四、AC代码 五、D…

自然语言(NLP)

It’s time for us to learn how to analyse natural language documents, using Natural Language Processing (NLP). We’ll be focusing on the Hugging Face ecosystem, especially the Transformers library, and the vast collection of pretrained NLP models. Our proj…

JuiceFS v1.2-beta1,Gateway 升级,多用户场景权限管理更灵活

JuiceFS v1.2-beta1 今天正式发布。在这个版本中&#xff0c;除了进行了大量使用体验优化和 bug 修复外&#xff0c;新增三个特性&#xff1a; Gateway 功能扩展&#xff1a;新增了“身份和访问管理&#xff08;Identity and Access Management&#xff0c;IAM&#xff09;” 与…

WHM中如何查看磁盘使用情况

今日看到有用户在论坛留言反馈他买了Hostease 独立服务器并购买cPanel面板&#xff0c;想要通过面板查看当前服务器使用的磁盘情况&#xff0c;但是不知道如何查看。因为这边也是对于cPanel即WHM面板有是有所了解的&#xff0c;对于这个用户的问题&#xff0c; 操做步骤如下&am…

【Linux】Docker 安装部署 Nacos

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ 【Linux】Docker 安装部署 Nacos docker搜索na…

看完这篇文章我奶奶都懂Opentracing了(一)

前言 如果要基于Opentracing开发分布式链路追踪Java客户端工具包&#xff0c;首先肯定需要了解Opentracing中的各种概念&#xff0c;包括但不限于Span和Scope等&#xff0c;其实这些概念在Opentracing的官方文档中是有比较详尽的说明的&#xff0c;英文不好也能靠着机器翻译读…

【linux-IMX6ULL中断配置流程】

目录 1. Cortex-A7和GIC中断概述1. 1 Cortex-A7中断系统&#xff1a;1. 2 GIC中断控制器简介&#xff1a; 2. 中断配置概述3. 底层中断文件配置3.1 对启动文件.s的配置思路3.2 对中断函数配置思路 4. 上层中断配置流程 1. Cortex-A7和GIC中断概述 学习IMX6UL的中断处理系统&…

毕业就业信息|基于Springboot+vue的毕业就业信息管理系统的设计与实现(源码+数据库+文档)

毕业就业信息管理系统 目录 基于Springboot&#xff0b;vue的毕业就业信息管理系统设计与实现 一、前言 二、系统设计 三、系统功能设计 1学生信息管理 2 公司信息管理 3公告类型管理 4公告信息管理 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设…

自动化运维管理工具 Ansible-----【inventory 主机清单和playbook剧本】

目录 一、inventory 主机清单 1.1inventory 中的变量 1.1.1主机变量 1.1.2组变量 1.1.3组嵌套 二、Ansible 的脚本 ------ playbook&#xff08;剧本&#xff09; 2.1 playbook介绍 2.2playbook格式 2.3playbooks 的组成 2.4playbook编写 2.5运行playbook 2.5.1ans…

如何翻译外文文献【攻略】

如何翻译外文文献【攻略】 前言版权推荐如何翻译外文文献简单描述第一步 准备一篇外文文献第二步 翻译网站第三步 解锁文档第四步 编辑dpf第五步 pdf转为word第六步 编辑word方便操作快捷键设置章节设置页眉页脚设置页码三线表的绘制 第七步 word转为pdf 最后 前言 2024-5-7 1…

电脑提示“无法定位程序输入点kernel32.dll”怎么解决?分享kernel32.dll丢失的五个修复方法

打开游戏或者软件的时候&#xff0c;电脑提示由于找不到kernel32.dll&#xff0c;无法继续执行此代码怎么办&#xff0c;其实修复起来不难。首先需要先知道怎么是dll文件&#xff0c;dll文件可以简单的把库文件看成一种代码仓库&#xff0c;它提供给使用者一些可以直接拿来用的…

【SSM进阶学习系列丨分页篇】PageHelper 分页插件集成实践

文章目录 一、说明什么是分页PageHelper介绍 二、导入依赖三、集成Spring框架中四、编写Service五、编写Controller六、编写queryAllByPage页面展示数据 一、说明 什么是分页 ​ 针对分页&#xff0c;使用的是PageHelper分页插件&#xff0c;版本使用的是5.1.8 。 ​ 参考文档…

openEuler 22.03 GPT分区表模式下磁盘分区管理

目录 GPT分区表模式下磁盘分区管理parted交互式创建分区步骤 1 执行如下步骤对/dev/sdc磁盘分区 非交互式创建分区步骤 1 输入如下命令直接创建分区。 删除分区步骤 1 执行如下命令删除/dev/sdc1分区。 GPT分区表模式下磁盘分区管理 parted交互式创建分区 步骤 1 执行如下步骤…

Day 24 数据库管理及数据类型

数据库管理及数据类型 一&#xff1a;数据类型 1.数值类型 整数类型 ​ 整数类型&#xff1a;TINYINT SMALLINT MEDIUMINT INT BIGINT ​ 作用&#xff1a;用于存储用户的年龄、游戏的Level、经验值等 浮点数类型 ​ 浮点数类型&#xff1a;FLOAT DOUBLE ​ 作用&#xf…

2024 cleanmymac有没有必要买呢,全反面分析

在使用mac时&#xff0c;小编遇到了运行内存不足、硬盘空间不足的情况。遇到这种情况&#xff0c;我们可以借助经典的电脑深度清理软件——CleanMyMac X&#xff0c;清理不常用的软件和系统垃圾&#xff0c;非常好用&#xff01;不过&#xff0c;有许多网友发现CleanMyMac X有免…

基于Springboot的校园新闻管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的校园新闻管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构…

NFTScan 与 Scattering 达成合作伙伴,双方将共同解决混合 NFT 数据需求

在区块链领域&#xff0c;NFT 的创新与发展从未停止。近日&#xff0c;NFT 数据基础设施 NFTScan 与一站式混合 NFT 交易市场 Scattering 达成合作伙伴关系&#xff0c;双方将在 NFT 数据层面展开合作&#xff0c;共同解决混合 NFT 的独特数据需求&#xff0c;Scattering 在协议…

非平衡数据处理-Tomek link算法介绍,代码和实战测评

作者Toby&#xff0c;来源公众号&#xff1a;Python风控模型&#xff0c;非平衡数据处理-Tomek link算法 概述 非平衡数据在金融风控领域、反欺诈客户识别、广告智能推荐和生物医疗中普遍存在。一般而言&#xff0c;不平衡数据正负样本的比例差异极大&#xff0c;如在Kaggle竞…

Quora 首席执行官亚当·德安杰洛 (Adam D’Angelo) 谈论了 AI、聊天机器人平台 Poe,以及 OpenAI 为什么不是竞争对手

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…