【数据结构】- 几个步骤教你认识并实现一个链表之带头(哨兵位)双向循环链表(中)

news2024/9/22 3:53:12

文章目录

  • 前言
  • 🌟一、带头双向循环链表
    • 🌏1.1头删:
      • 💫1.1.1代码:
      • 💫1.1.2流程图:
    • 🌏1.2尾删:
      • 💫1.2.1代码:
      • 💫1.2.2流程图:
    • 🌏1.3查找:
    • 🌏1.4在pos位置之前插入:
      • 💫1.4.1代码:
      • 💫1.4.2流程图:
    • 🌏1.5在pos位置删除:
      • 💫1.5.1代码:
      • 💫1.5.2代码:
    • 🌏1.6释放链表:
  • 🌟二、完整带头双向循环链表
  • 😽总结


前言

👧个人主页:@小沈熬夜秃头中୧⍤⃝❅
😚小编介绍:欢迎来到我的乱七八糟小星球🌝
📋专栏:数据结构
🔑本章内容:[数据结构]—链表之带头双向循环链表
送给各位💌:不谈以前不说如果只希望未来越来越好
欢迎 评论📝 +点赞👍 +收藏😽 +关注💞哦~


提示:以下是本篇文章正文内容,下面案例可供参考

🌟一、带头双向循环链表

🌏1.1头删:

💫1.1.1代码:

void LTPopFront(LTNode* phead)
{
	assert(phead);
	LTNode* cur = phead->next;
	phead->next = cur->next ;
	cur->next->prev = phead;
	free(cur);
}

💫1.1.2流程图:

定义一个指针时:(代码如上图)

请添加图片描述

定义两个指针时:(建议使用两个—代码如下图)

请添加图片描述

🌏1.2尾删:

💫1.2.1代码:

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

💫1.2.2流程图:

第一种:

请添加图片描述

第二种:

请添加图片描述

第三种:需要注意

请添加图片描述

🌏1.3查找:

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;
}

🌏1.4在pos位置之前插入:

💫1.4.1代码:

void LTInsert(LTNode* pos, LTDataType x)
{
	assert(pos);
	LTNode* newnode = BuyLTNode(x);
	pos->prev->next  = newnode;
	newnode->prev = pos->prev;
	newnode->next = pos;
	pos->prev = newnode;
	
	//第二种:
	///LTNode* prev = pos->prev;
	//prev->next = newnode;
	//newnode->prev = prev;
	//pos->prev = newnode;
	//newnode->next = pos;
}

💫1.4.2流程图:

第一种:

请添加图片描述

第二种:

在这里插入图片描述

🌏1.5在pos位置删除:

💫1.5.1代码:

void LTErase(LTNode* pos)//要注意不能传哨兵位
{
	assert(pos);
	LTNode* posPrev = pos->prev;
	LTNode* posNext = pos->next;
	posPrev->next = posNext;
	posNext->prev = posPrev;
	free(pos);
}

💫1.5.2代码:

请添加图片描述

🌏1.6释放链表:

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

🌟二、完整带头双向循环链表

请添加图片描述

//List.h
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

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

LTNode* LTInit();
void LTNodePrint(LTNode* phead);
bool LTEmpty(LTNode* phead);
void LTPushFront(LTNode* phead, LTDataType x);
void LTPushBack(LTNode* phead, LTDataType x);
void LTPopFront(LTNode* phead);
void LTPopBack(LTNode* phead);
LTNode* LTFind(LTNode* phead, LTDataType x);
//在pos之前插入
void LTInsert(LTNode* pos, LTDataType x);
//删除pos位置的值
void LTErase(LTNode* pos);
void LTDestroy(LTNode* phead);

//List.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"List.h"
bool LTEmpty(LTNode* phead)
{
	assert(phead);
	return phead->next == phead;
}
LTNode* BuyLTNode(LTDataType x)
{
	LTNode* newnode = (LTNode*)malloc(sizeof(LTNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
	}
	newnode->data = x;
	newnode->next = NULL;
	newnode->prev = NULL;
	return newnode;
}
LTNode* LTInit()
{
	LTNode* phead = BuyLTNode(-1);
	phead->next = phead;
	phead->prev = phead;
	return phead;
}

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

void LTPushFront(LTNode* phead, LTDataType x)
{
	LTNode* newnode = BuyLTNode(x);
	LTNode* cur = phead->next;
	newnode->prev = phead;
	phead->next = newnode;
	newnode->next = cur;
	cur->prev = newnode;
}

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

void LTPopFront(LTNode* phead)
{
	assert(phead);
	LTNode* cur = phead->next;
	//LTNode* next = cur->next;
	phead->next = cur->next ;
	cur->next->prev = phead;
	free(cur);
}

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

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 = BuyLTNode(x);
	pos->prev->next  = newnode;
	newnode->prev = pos->prev;
	newnode->next = pos;
	pos->prev = newnode;
	//第二种:
	///LTNode* prev = pos->prev;
	//prev->next = newnode;
	//newnode->prev = prev;
	//pos->prev = newnode;
	//newnode->next = pos;
}

void LTErase(LTNode* pos)//要注意不能传哨兵位
{
	assert(pos);
	LTNode* posPrev = pos->prev;
	LTNode* posNext = pos->next;
	posPrev->next = posNext;
	posNext->prev = posPrev;
	free(pos);
}
void LTDestroy(LTNode* phead)
{
	assert(phead);
	LTNode* cur = phead->next;
	while (cur != phead)
	{
		LTNode* next = cur->next;
		free(cur);
		cur = next;
	}
	free(phead);
}

//Test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"List.h"
void TestList()
{
	LTNode* plist = LTInit();
	LTPushBack(plist, 1);
	LTPushBack(plist, 2);
	LTPushBack(plist, 3);
	LTPushBack(plist, 4);
	LTNodePrint(plist);
	//LTPushFront(plist, 1);
	//LTPushFront(plist, 2);
	//LTPushFront(plist, 3);
	//LTPushFront(plist, 4);
	//LTNodePrint(plist);
	/*LTPopBack(plist);
	LTNodePrint(plist);*/
	/*LTPopFront(plist);
	LTNodePrint(plist);*/
	/*LTNode* pos = LTFind(plist,3);
	if (pos)
	{
		LTInsert(pos, 30);
	}
	LTNodePrint(plist);*/
	LTNode* pos = LTFind(plist, 2);
	if (pos)
	{
		LTErase(pos, 30);
	}
	LTNodePrint(plist);
	LTDestroy(plist);
	plist = NULL;
}
int main()
{
	TestList();
	return 0;
}

😽总结

请添加图片描述
😽Ending,今天的链表之带头双向循环链表(中)的内容就到此结束啦~,如果后续想了解更多,就请关注我吧,一键三连哦 ~

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

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

相关文章

5. Mysql索引优化实战二

MySQL性能调优 1. 分页查询优化1.1 根据自增且连续的主键排序的分页查询1.2 根据非主键字段排序的分页查询 2. Join关联查询优化 本文是按照自己的理解进行笔记总结&#xff0c;如有不正确的地方&#xff0c;还望大佬多多指点纠正&#xff0c;勿喷。 本节课内容&#xff1a; 1…

HTTP第七讲——HTTP报文

报文结构 拿 TCP 报文来举例&#xff0c;它在实际要传输的数据之前附加了一个 20 字节的头部数据&#xff0c;存储 TCP 协议必须的额外信息&#xff0c;例如发送方的端口号、接收方的端口号、包序号、标志位等等。 有了这个附加的 TCP 头&#xff0c;数据包才能够正确传输&…

HTML 基础知识

HTML基础知识 1. VSCode的安装与配置 下载地址 https://code.visualstudio.com/ 安装插件 Live Server Auto Rename Tag 自动格式化 点击 settings&#xff0c;然后输入format&#xff0c;然后勾选上 Format On Save。 2. HTML 基础标签 2.1 文件结构 快捷键&#xff1…

安卓实现左侧列表选择项点击,右侧fragment切换

安卓实现左侧列表选择项点击&#xff0c;右侧fragment切换 问题背景 安卓日常开发中&#xff0c;有时候需要开发页面中&#xff0c;显示左侧会列表选择项&#xff0c;点击不同的选项后右侧切换fragment显示&#xff0c;本文将介绍实现的一个思路。 问题分析 要实现的效果如…

前端三剑客 HTML+CSS+JS

文章目录 一、HTML1.1 基础标签1.2 列表1.3 表格1.4 表单 二、CSS2.1 引入方式2.2 CSS 选择器2.2.1 基本选择器2.2.2 组合选择器 2.3 常用属性2.3.1 背景2.3.2 文本2.3.3 字体2.3.4 display元素类型2.3.5 浮动2.3.6 盒子模型 三、JavaScript3.1 引入方式3.2 数据类型3.2.1 数组…

tomcat集群下的session共享和负载均衡

环境 操作系统&#xff1a;windows tomcat1&#xff1a;Apache Tomcat/7.0.52&#xff08;8085&#xff09; tomcat2&#xff1a;Apache Tomcat/7.0.52&#xff08;8086&#xff09; jre&#xff1a;1.7.0_80 nginx&#xff1a;nginx-1.20.1&#xff08;8070&#xff09; redis…

cmd@快捷键方式@静默执行命令@修复桌面空白快捷方式图标

文章目录 ref前言快捷方式执行命令行或打开文件eg:直接打开某个文件 创建快捷方式eg:快捷方式运行命令 修复快捷方式图标空白问题逐个修复批量修复一次性操作:逐步操作 执行效果第三方工具修复 ref How can I execute a Windows command line in background? - Super Userstb…

2022年5个不寻常的Web3预测

正如埃隆马斯克所说&#xff0c;“最有趣的结果是最有可能的”。所以&#xff0c;这是我对web3的5个不同寻常的预测&#xff0c;下面我将详细介绍我是如何得出这些想法的&#xff1a; 口袋妖怪训练师将是一份全职工作有人会使用JPEG支持的贷款购买房屋(IRL)DAO将收购一家上市公…

并发编程11:Synchronized与锁升级

文章目录 11.1 面试题11.2 Synchronized的性能变化11.3 Synchronized锁种类及升级步骤11.3.1 多线程访问情况11.3.2 升级流程11.3.3 无锁11.3.4 偏锁11.3.5 轻锁11.3.6 重锁11.3.7 小总结 11.4 JIT编译器对锁的优化11.4.1 JIT11.4.2 锁消除11.4.3 锁粗化 11.5 小总结 11.1 面试…

电影《银河护卫队3》观后感

上周看了电影《银河护卫队3》&#xff0c;本部电影&#xff0c;主要是围绕着主角团队中的一个队员展开叙事的&#xff0c;在团队中&#xff0c;这名队员叫“火箭”&#xff0c;是一只经过基因改造过的浣熊。 当初进行改造的团队&#xff0c;是一家拥有基因改造技术的团队&…

基于SpringBoot, Vue实现的校园二手书交易系统

背景 在Internet高速发展的今天&#xff0c;计算机的应用几乎完全覆盖我们生活的各个领域&#xff0c;互联网在经济&#xff0c;生活等方面有着举足轻重的地位&#xff0c;成为人们资源共享&#xff0c;信息快速传递的重要渠道。在中国&#xff0c;网上管理的兴起也同时飞速发…

Solidity中哈希函数的编码与解码

起因 写这篇文章的起因&#xff0c;是我在前端调试合约的时候&#xff0c;发现合约报错了&#xff0c;点开命令行报错&#xff0c;发现返回的是合约的 callData&#xff0c;我直接表演一个眼前一黑&#xff0c;我怎么直接的知道是调用哪个方法的时候报错呢&#xff1f; 于是有…

【网络基础知识概念】路由器,交换机,无线AP,DHCP,DNS,WAN接口和LAN接口是什么?(附实物图详解)

【写在前面】其实在做一些试题的时候&#xff0c;经常会有些概念性的东西完全不清楚&#xff0c;今天我就带大家整理一下&#xff0c;交换机是啥&#xff1f;路由器是啥&#xff1f;无线AP是啥&#xff1f;ADSL又是什么&#xff0c;啥叫DHCP&#xff0c;DNS又是啥&#xff1f;W…

改进YOLOv5 | C3模块改动篇 | 轻量化设计 |骨干引入动态卷积|CondConv

CondConv: Conditionally Parameterized Convolutions for Efficient Inference 卷积是当前CNN网络的基本构成单元之一,它的一个基本假设是:卷积参数对所有样例共享。作者提出一种条件参数卷积,它可以为每个样例学习一个特定的卷积核参数,通过替换标准卷积,CondConv可以提…

shell脚本之“sort“、“uniq“、“tr“、“cut“命令详解

文章目录 sort命令uniq命令tr命令cut命令 sort命令 以行为单位对文件内容进行排序&#xff0c;也可以根据不同的数据类型来排序. 比较原则&#xff1a;从首字符向后&#xff0c;依次按ASCII码值进行比较&#xff0c;最后将他们按升序输出. 语法格式 sort [选项] 参数 cat …

c++ this指针

this指针介绍&#xff1a; c中成员变量和成员函数分开存储&#xff0c;每一个非静态成员函数只会有一个实例&#xff0c;多个同类型对象共用这一个成员函数。那么代码怎么区分哪个对象调用自己呢&#xff1f;this指针由此应运而生。 c通过提供对象指针&#xff0c;this指针。…

2020年下半年软件设计师下午试题

【试题四】希尔排序 【说明】 希尔排序算法又称最小增量排序算法&#xff0c;其基本思想是&#xff1a; 步骤1 :构造一个步长序列delta、deltak、 deltak &#xff0c;其中delta1n/2 &#xff0c;后面的每个delta是前一个的1/2 &#xff0c; deltak1&#xff1b; 步骤2 :根…

【shell脚本里的命令】

目录 一、sort命令1.1、命令演示 二、unip命令1、命令演示1、列题:2、使用脚本来查看用户有没有被恶意登录&#xff0c;查看登录用户的对应ip地址 三、tr命令1.1、命令演示1.2、使用tr命令对数组进行排序 五、从Windows里拉文件到Linux系统中要做的潜在条件六、cut命令 一、sor…

vue 阻止事件冒泡和捕获

文章目录 1. js 事件的三阶段2. js 阻止事件冒泡&#xff0c;捕获3、JavaScript基础知识&#xff1a;preventDefault和stopPropagationpreventDefault()事件方法stopPropagation()事件方法 click.stop : 阻止事件冒泡 click.prevent : 阻止事件默认行为 click.self : 事件只作用…

卡尔曼滤波器-公式推导 | 原理分析 | 将卡尔曼滤波器在MatLab中简单实现

目录 1.状态转移2.协方差矩阵3.噪声协方差矩阵的传递4.观测矩阵5.状态更新6.噪声协方差矩阵的更新7.在MatLab中实现卡尔曼滤波器1.状态转移 卡尔曼滤波器又称为最佳线性滤波器。优点有实现简单、纯时域滤波器、不需要进行频域变换等。 假设有一辆汽车在路上行驶,用位置和速度…