【数据结构】04.双向链表

一、双向链表的结构

在这里插入图片描述

注意:这里的“带头”跟前面我们说的“头节点”是两个概念,带头链表里的头节点,实际为“哨兵位”,哨兵位节点不存储任何有效元素,只是站在这里“放哨的”。
“哨兵位”存在的意义:遍历循环链表避免死循环。

二、双向链表的实现

2.1 双向链表结点的创建

typedef int DLType;
//创建结构体
typedef struct DList
{DLType data;struct DList* prev;struct DList* next;
}DL;

2.2 双向链表的初始化与销毁

//初始化phead
DL* init(void)
{DL* phead = BuyNewNode(0);return phead;
}
//销毁链表,这里需要主要phead是形参,这里的最后将phead置空并不能将原链表中的phead置空,
//因此原链表中的phead需要手动置空,详细实现见源码
void DLDesdroy(DL* phead)
{assert(phead);DL* tail =phead->next;while (tail != phead){DL* next = tail->next;free(tail); tail= next;}free(phead);phead = NULL;
}

2.3 双向链表的增删查改

由于多次创建结点,因此我们将它提炼为一个函数

//创造新的节点
DL* BuyNewNode(DLType  x)
{DL* newnode = (DL*)malloc(sizeof(DL));if (newnode == NULL){perror("malloc is failed!\n");return 1;}newnode->data = x;newnode->next = newnode->prev = newnode;return newnode;
}
//尾插
void  DLPushBack(DL* phead,DLType x)
{assert(phead);DL* newnode = BuyNewNode(x);newnode->next = phead;phead->prev->next = newnode;newnode->prev = phead->prev;phead->prev = newnode;
}//尾删
void DLPopBack(DL* phead)
{assert(phead);assert(phead->next != phead);DL* tail = phead->prev;DL* prev = tail->prev;prev->next = phead;phead->prev = prev;free(tail);tail = NULL;  }//头插
void DLPushFront(DL* phead, DLType x)
{assert(phead);DL* newnode = BuyNewNode(x);DL* first = phead->next;newnode->next = first;first->prev = newnode;phead->next = newnode;newnode->prev=phead;
}//头删
void DLPopFront(DL* phead)
{assert(phead);assert(phead->next != phead);DL* first = phead->next;DL* second = first->next;phead->next = second;second->prev = phead;free(first);first = NULL;
}//查找
DL* DLFind(DL* phead,DLType x)
{assert(phead);DL* cur = phead->next;while ( cur != phead){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}//pos位置插入数据
void DLInsert(DL* pos,DLType x)
{assert(pos);DL* newnode = BuyNewNode(x);DL* prev = pos->prev;prev->next = newnode;newnode->prev = prev;newnode->next = pos;pos->prev = newnode;
}//pos位置之后插入数据
void DLInsertAfter(DL* pos, DLType x)
{assert(pos);DL* newnode = BuyNewNode(x);DL* next = pos->next;newnode->next = next;next->prev = newnode;pos->next = newnode;newnode->prev = pos;
}//删除pos位置元素
void  DLErase(DL* pos)
{assert(pos);DL* next = pos->next;DL* prev = pos->prev;prev->next = next;next->prev = prev;free(pos);pos = NULL;
}

2.4 双向链表的打印

//打印链表
void DLPrint(DL* phead)
{DL* pcur = phead->next;while (pcur != phead){printf("%d->", pcur->data);pcur = pcur->next;}printf("NULL\n");
}

2.5 双向链表的源码

//DL.h#pragma once#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int DLType;typedef struct DList
{DLType data;struct DList* prev;struct DList* next;
}DL;//初始化
DL* init(void);
//打印
void DLPrint(DL* phead);//尾插、尾删
void  DLPushBack(DL* phead, DLType x);
void DLPopBack(DL* phead);//头插、头删
void  DLPushFront(DL* phead, DLType x);
void  DLPopFront(DL* phead);//查找
DL* DLFind(DL* phead, DLType x);//指定位置插入数据、指定位置之后插入数据
void  DLInsert(DL* pos, DLType x);
void DLInsertAfter(DL* pos, DLType x);//删除pos
void  DLErase(DL* phead);void DLDesdroy(DL** phead);
//DL.c
#include "DList.h"//创造新的节点
DL* BuyNewNode(DLType  x)
{DL* newnode = (DL*)malloc(sizeof(DL));if (newnode == NULL){perror("malloc is failed!\n");return 1;}newnode->data = x;newnode->next = newnode->prev = newnode;return newnode;
}//初始化phead
DL* init(void)
{DL* phead = BuyNewNode(0);return phead;
}//打印链表
void DLPrint(DL* phead)
{DL* pcur = phead->next;while (pcur != phead){printf("%d->", pcur->data);pcur = pcur->next;}printf("NULL\n");
}//尾插
void  DLPushBack(DL* phead,DLType x)
{assert(phead);DL* newnode = BuyNewNode(x);newnode->next = phead;phead->prev->next = newnode;newnode->prev = phead->prev;phead->prev = newnode;
}//尾删
void DLPopBack(DL* phead)
{assert(phead);assert(phead->next != phead);DL* tail = phead->prev;DL* prev = tail->prev;prev->next = phead;phead->prev = prev;free(tail);tail = NULL;  }//头插
void DLPushFront(DL* phead, DLType x)
{assert(phead);DL* newnode = BuyNewNode(x);DL* first = phead->next;newnode->next = first;first->prev = newnode;phead->next = newnode;newnode->prev=phead;
}//头删
void DLPopFront(DL* phead)
{assert(phead);assert(phead->next != phead);DL* first = phead->next;DL* second = first->next;phead->next = second;second->prev = phead;free(first);first = NULL;
}//查找
DL* DLFind(DL* phead,DLType x)
{assert(phead);DL* cur = phead->next;while ( cur != phead){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}//pos位置插入数据
void DLInsert(DL* pos,DLType x)
{assert(pos);DL* newnode = BuyNewNode(x);DL* prev = pos->prev;prev->next = newnode;newnode->prev = prev;newnode->next = pos;pos->prev = newnode;
}//pos位置之后插入数据
void DLInsertAfter(DL* pos, DLType x)
{assert(pos);DL* newnode = BuyNewNode(x);DL* next = pos->next;newnode->next = next;next->prev = newnode;pos->next = newnode;newnode->prev = pos;
}//删除
void  DLErase(DL* pos)
{assert(pos);DL* next = pos->next;DL* prev = pos->prev;prev->next = next;next->prev = prev;free(pos);pos = NULL;
}//销毁链表
void DLDesdroy(DL* phead)
{assert(phead);DL* tail =phead->next;while (tail != phead){DL* next = tail->next;free(tail); tail= next;}free(phead);phead = NULL;
}

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

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

相关文章

Roboflow自动标定数据集

最近需要自己打数据集&#xff0c;记录一下用Roboflow来打标签。 https://roboflow.com/&#xff08;官网&#xff09; 进入官网先注册&#xff0c;注册完成后进入这个界面。 我先讲如果不想让数据集公开怎么办&#xff0c;因为这里每个新建的都是公开的。新账号进去应该进去…

【数据分享】国家级旅游休闲街区数据(Excel/Shp格式/免费获取)

之前我们分享过从我国文化和旅游部官网整理的2018-2023年我国50个重点旅游城市星级饭店季度经营状况数据&#xff08;可查看之前的文章获悉详情&#xff09;&#xff01;文化和旅游部官网上也分享有很多与旅游相关的常用数据&#xff0c;我们基于官网发布的名单文件整理得到全国…

Qt Creator13配置Android开发环境

QT Creator13是目前&#xff08;2024年&#xff09;最新版本&#xff0c;配置Android开发环境有一些不一样&#xff0c;走了一些弯路&#xff0c;记录如下。 1、安装JDK和SDK 下载安装JDK和SDK&#xff0c;建议安装在无空格和中文字符的目录下。 具体安装步骤不再赘述&#…

GraalVM

文章目录 1、什么是GraalVM2、GraalVM的两种模式1_JIT模式2_AOT模式3_总结 3、应用场景1_SpringBoot搭建GraalVM应用2_函数计算3_Serverless应用 4、参数优化和故障诊断1_内存快照文件的获取2_运行时数据的获取 1、什么是GraalVM GraalVM是Oracle官方推出的一款高性能JDK&…

如何改善提示词,让 GPT-4 更高效准确地把视频内容整体转换成文章?

&#xff08;注&#xff1a;本文为小报童精选文章。已订阅小报童或加入知识星球「玉树芝兰」用户请勿重复付费&#xff09; 让我们来讨论一下大语言模型应用中的一个重要原则 ——「欲速则不达」。 作为一个自认为懒惰的人&#xff0c;我一直有一个愿望&#xff1a;完成视频制作…

Spire.PDF for .NET【文档操作】演示:以特定的缩放比例/百分比打开 PDF 文件

有时&#xff0c;我们可能需要在显示 PDF 文件时更改缩放比例以满足我们的要求。在本文中&#xff0c;我们将演示如何使用 Spire.PDF for .NET 以特定的缩放比例/百分比&#xff08;例如默认值、100% 或任何其他所需的缩放比例&#xff09;打开 PDF 文件。 Spire.PDF for .NET…

Renesas R7FA8D1BH (Cortex®-M85) I2C接口应用(OLED)

目录 概述 1 软硬件 1.1 软硬件环境信息 1.2 开发板信息 1.3 调试器信息 2 FSP和KEIL配置I2C 2.1 I2C硬件电路 2.2 FSP配置参数 3 软件功能实现 3.1 FSP生成项目 3.2 FSP中I2C接口函数 3.2.1 I2C Master的函数列表 3.2.2 函数功能介绍 3.3 I2C接口 4 验证i2c接口…

Vant Design - VUE 时间区间限制

效果图&#xff0c;限制7天 实现代码 <a-range-picker v-model"dateTime" style"width: 100%" :disabled-date"disabledDate" format"YYYY-MM-DD HH:mm:ss" :showTime"true" :placeholder"[开始时间, 结束时间]&quo…

浅析MySQL-索引篇01

什么是索引&#xff1f; 索引是帮助存储引擎快速获取数据的一种数据结构&#xff0c;类似于数据的目录。 索引的分类 按数据结构分类&#xff1a; MySQL 常见索引有 BTree 索引、HASH 索引、Full-Text 索引。 Innodb是MySQL5.5之后的默认存储引擎&#xff0c;BTree索引类型也…

量产工具一一文字系统(三)

目录 前言 一、文字数据结构抽象 1.描述一个文字的位图 2.描述一个字库操作 3.font_manager.h 二、实现Freetype封装 1.freetype.c 三、实现文字管理 1.font_manager.c 四、单元测试 1.font_test.c 2.disp_manager.c 3.disp_manager.h 4.上机测试 前言 前面我们…

从搜索框的提示词中再探防抖和节流

前言 最近逛掘金时&#xff0c;看到了一篇文章。发现是我之前写过的一篇文章主题是防抖和节流的&#xff0c;看防抖时没感觉哪里不一样&#xff0c;但是当我看到节流时发现他的节流怎么这么繁琐(・∀・(・∀・(・∀・*)&#xff1f; 抱着疑惑的想法&#xff0c;我仔细拜读了这…

深度学习简介-AI(三)

深度学习简介 深度学习简介深度学习例子深度学习训练优化1.随机初始化2.优化损失函数3.优化器选择4.选择/调整模型结构 深度学习常见概念隐含层/中间层随机初始化损失函数导数与梯度优化器Mini Batch/epoch 深度学习训练逻辑图 深度学习简介 深度学习例子 猜数字 A: 我现在心…

机器学习Day10:聚类

概念 聚类是按照某个特定标准把一个数据集分割成不同的类或簇&#xff0c;使得同一个簇内的数据对象的相似性尽可能大&#xff0c;同时不在同一个簇中的数据对象的差异性尽可能大 聚类的过程 数据准备&#xff1a;特征标准化和降维特征选择&#xff1a;从最初的特征中选择最…

rust 终端显示综合例程

文章目录 demo程序1 terminal_size2 term_grid3 crossterm3.1 style 4 lscolors准备内容4.1 LsColors 5 users5.1 获取用户/用户组信息5.2 通过缓存获取 demo程序 综合demo 各个库使用demo 1 terminal_size 一个获取终端界面大小的库&#xff0c;支持linux、macos、windows。…

keil5模拟 仿真 报错没有读写权限

debug*** error 65: access violation at 0x4002100C : no write permission 修改为&#xff1a; Dialog DLL默认是DCM3.DLL Parameter默认是-pCM3 应改为 Dialog DLL默认是DARMSTM.DLL Parameter默认是-pSTM32F103VE

【机器学习】机器学习与电商推荐系统的融合应用与性能优化新探索

文章目录 引言第一章&#xff1a;机器学习在电商推荐系统中的应用1.1 数据预处理1.1.1 数据清洗1.1.2 数据归一化1.1.3 特征工程 1.2 模型选择1.2.1 协同过滤1.2.2 矩阵分解1.2.3 基于内容的推荐1.2.4 混合推荐 1.3 模型训练1.3.1 梯度下降1.3.2 随机梯度下降1.3.3 Adam优化器 …

苹果电脑如何录屏,3个方法,帮你搞定

“最近新买了一台苹果电脑&#xff0c;但这是我第一次使用&#xff0c;有很多功能都不太了解。想问问大家苹果电脑如何录屏啊&#xff1f;可以教我一下吗&#xff1f;先提前谢谢大家啦&#xff01;” 苹果电脑以其出色的性能和独特的设计&#xff0c;深受全球用户的喜爱。而在…

Win11禁止右键菜单折叠的方法

背景 在使用windows11的时候&#xff0c;会发现默认情况下&#xff0c;右键菜单折叠了。以至于在使用一些软件的右键菜单时总是要点击“显示更多选项”菜单展开所有菜单&#xff0c;然后再点击。而且每次在显示菜单时先是全部展示&#xff0c;再隐藏一下&#xff0c;看着着实难…

源代码层面分析Appium-inspector工作原理

Appium-inspector功能 Appium Inspector 基于 Appium 框架&#xff0c;Appium 是一个开源工具&#xff0c;用于自动化移动应用&#xff08;iOS 和 Android&#xff09;和桌面应用&#xff08;Windows 和 Mac&#xff09;。Appium 采用了客户端-服务器架构&#xff0c;允许用户通…

51单片机嵌入式开发:STC89C52操作8八段式数码管原理

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 STC89C52操作8八段式数码管原理 1 8位数码管介绍1.1 8位数码管概述1.2 8位数码管原理1.3 应用场景 2 原理图图解2.1 74HC573原理2.2 74HC138原理2.3 数码管原理 3 数码管程序…