《数据结构:C语言实现双链表》

文章目录

    • 一、链表的分类
    • 二、双向链表
        • 1、概念与结构
    • 三、双向链表实现
        • 1、双向链表要实现的功能
        • 2、哨兵位初始化
        • 3、双链表头插数据
        • 4、判断链表是否为空
        • 5、打印链表数据
        • 6、尾插数据
        • 7、头删数据
        • 8、尾删数据
        • 9、寻找数据所在结点
        • 10、在任意结点之后插入数据
        • 11、删除任意结点
        • 12、销毁链表

一、链表的分类

链表的结构非常多样,以下情况组合起来就有八种(2×2×2)链表结构:

在这里插入图片描述

虽然有这么多的链表的结构,但我们实际中最常用的还是两种结构:单链表和双向带头循环链表.

  • 1、无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。
  • 2、带头双向循环链表:结构复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单,后面我们代码实现了就知道了。

二、双向链表

1、概念与结构

在这里插入图片描述

  • 注意:这⾥的“带头”跟前⾯我们说的“头结点”是两个概念,实际前⾯的在单链表阶段称呼不严谨.

带头链表中的头结点,实际为“哨兵位”,哨兵位结点补存储任何有效元素,只是站在这里“放哨的”

三、双向链表实现

1、双向链表要实现的功能

List.h文件中:

#pragma once#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>typedef int LTDateType;typedef struct ListNode
{LTDateType date;struct ListNode* next;//存放下个节点的地址struct ListNode* prev;//存放上一个结点的地址
}LT;//初始化哨兵位
void LTInit(LT** pphead);//初始化哨兵位,串一级指针更方便
LT* LTInit02();//头插
void LTPushFornt(LT* phead,LTDateType x);//尾插
void LTPushBack(LT* phead,LTDateType x);//打印数据
void LTPrint(LT* phead);//头删
void LTPopFront(LT* phead);//尾删
void LTPopBack(LT* phead);//判断链表是否为空
bool LTEmpty(LT* phead);//返回数据所在结点
LT* LTFind(LT* phead, LTDateType x);//在pos结点之后插入数据
void LTInsert(LT* pos, LTDateType x);//删除pos结点的数据
void LTErase(LT* pos);//销毁结点
void LTDesTroy(LT** pphead);//穿一级指针销毁,需要手动置空
void LTDeaTroy02(LT* phead);
2、哨兵位初始化
//开辟结点空间
LT* LTBuyNode(LTDateType x)
{LT* newnode = (LT*)malloc(sizeof(LT));if (newnode == NULL){perror("malloc fail");exit(1);}newnode->date = x;newnode->next = newnode;newnode->prev = newnode;
}//初始化哨兵位
void LTInit(LT** pphead)
{assert(pphead != NULL);*pphead = LTBuyNode(-1);
}//初始化哨兵位,串一级指针更方便
LT* LTInit02()
{LT* newnode = LTBuyNode(-1);return newnode;
}
3、双链表头插数据
//头插
void LTPushFornt(LT* phead, LTDateType x)
{assert(phead != NULL);LT* newnode = LTBuyNode(x);newnode->next = phead->next;newnode->prev = phead;phead->next->prev = newnode;phead->next = newnode;}
4、判断链表是否为空
//判断链表是否为空
bool LTEmpty(LT* phead)
{assert(phead != NULL);return phead->prev == phead;
}
5、打印链表数据
//打印数据
void LTPrint(LT* phead)
{assert(phead != NULL);LT* pcur = phead->next;while (pcur != phead){printf("%d->", pcur->date);pcur = pcur->next;}printf("\n");
}
6、尾插数据
//尾插
void LTPushBack(LT* phead, LTDateType x)
{assert(phead != NULL);LT* newnode = LTBuyNode(x);newnode->prev = phead->prev;newnode->next = phead;phead->prev->next = newnode;phead->prev = newnode;
}
7、头删数据
//头删
void LTPopFront(LT* phead)
{assert(phead);assert(!LTEmpty(phead));LT* del = phead->next;phead->next = del->next;del->next->prev = phead;free(del);del = NULL;
}
8、尾删数据
//尾删
void LTPopBack(LT* phead)
{assert(phead);assert(!LTEmpty(phead));LT* del = phead->prev;phead->prev = del->prev;del->prev->next = phead;free(del);del = NULL;
}
9、寻找数据所在结点
//返回数据所在结点
LT* LTFind(LT* phead, LTDateType x)
{assert(phead);LT* pcur = phead->next;while (pcur != phead){if (pcur->date == x){return pcur;}pcur = pcur->next;}return NULL;
}
10、在任意结点之后插入数据
//在pos结点之后插入数据
void LTInsert(LT* pos, LTDateType x)
{assert(pos != NULL);LT* newnode = LTBuyNode(x);newnode->next = pos->next;newnode->prev = pos;pos->next->prev = newnode;pos->next = newnode;
}
11、删除任意结点
//删除pos结点的数据
void LTErase(LT* pos)
{assert(pos);pos->next->prev = pos->prev;pos->prev->next = pos->next;free(pos);pos = NULL;
}
12、销毁链表
//销毁结点
void LTDesTroy(LT** pphead)
{assert(pphead);LT* pcur = (*pphead)->next;while (pcur != *pphead){LT* next = pcur->next;free(pcur);pcur = next;}free(*pphead);*pphead = pcur = NULL;
}//穿一级指针销毁,需要手动置空
void LTDeaTroy02(LT* phead)
{assert(phead);LT* pcur = phead->next;while (pcur != phead){LT* next = pcur->next;free(pcur);pcur = next;}free(phead);phead = pcur =NULL;
}

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

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

相关文章

FastGPT 代码调试配置

目录 一、添加 launch.json 文件 二、调试 本文简单介绍如何通过 vscode 对 FastGPT 进行调试。 这里假设已经安装 vsocde 和 FastGPT本地部署。 一、添加 launch.json 文件 vscode 打开 FastGPT 项目&#xff0c;点击 调试 -> 显示所有自动调试配置 -> 添加配置 -&…

IDEA创建Java工程、Maven安装与建立工程、Web工程、Tomcat配置

《IDEA破解、配置、使用技巧与实战教程》系列文章目录 第一章 IDEA破解与HelloWorld的实战编写 第二章 IDEA的详细设置 第三章 IDEA的工程与模块管理 第四章 IDEA的常见代码模板的使用 第五章 IDEA中常用的快捷键 第六章 IDEA的断点调试&#xff08;Debug&#xff09; 第七章 …

响应式编程(Reactive Programming)是什么?

响应式编程的概念 Reactive Programming(反应式编程或响应式编程)是一种面向数据流和变化传播的编程范式,它允许程序组件以声明式的方式响应数据的变化。 响应式编程强调以数据流作为核心,利用观察者模式等机制自动处理数据的变化和传播。 响应式编程的核心思想 以异步数…

【Nacos】Nacos服务注册与发现 心跳检测机制源码解析

在前两篇文章&#xff0c;介绍了springboot的自动配置原理&#xff0c;而nacos的服务注册就依赖自动配置原理。 Nacos Nacos核心功能点 服务注册 :Nacos Client会通过发送REST请求的方式向Nacos Server注册自己的服务&#xff0c;提供自身的元数据&#xff0c;比如ip地址、端…

JVM监控及诊断工具-命令行篇--jcmd命令介绍

JVM监控及诊断工具-命令行篇5-jcmd&#xff1a;多功能命令行 一 基本情况二 基本语法jcmd -ljcmd pid helpjcmd pid 具体命令 一 基本情况 在JDK 1.7以后&#xff0c;新增了一个命令行工具jcmd。它是一个多功能的工具&#xff0c;可以用来实现前面除了jstat之外所有命令的功能…

pyspark使用 graphframes创建和查询图的方法

1、安装graphframes的步骤 1.1 查看 spark 和 scala版本 在终端输入&#xff1a; spark-shell --version 查看spark 和scala版本 1.2 在maven库中下载对应版本的graphframes https://mvnrepository.com/artifact/graphframes/graphframes 我这里需要的是spark 2.4 scala 2.…

QDockWidget

详细描述 QDockWidget 类提供了一个小部件&#xff0c;它可以停靠在QMainWindow内部&#xff0c;也可以作为桌面上的顶级窗口浮动。 QDockWidget 提供了停靠部件的概念&#xff0c;也称为工具调色板或实用窗口。停靠窗口是放置在 中央部件 周围的停靠部件区域中的辅助窗口&am…

AI算法24-决策树C4.5算法

目录 决策树C4.5算法概述 决策树C4.5算法简介 决策树C4.5算法发展历史 决策树C4.5算法原理 信息熵&#xff08;Information Entropy&#xff09; 信息增益&#xff08;Information Gain&#xff09; 信息增益比&#xff08;Gain Ratio&#xff09; 决策树C4.5算法改进 …

Golang中读写锁的底层实现

目录 Sync.RWMutex 背景与机制 接口简单介绍 sync.RWMutex 数据结构 读锁流程 RLock RUnlock RWMutex.rUnlockSlow 写锁流程 Lock Unlock Sync.RWMutex 背景与机制 从逻辑上&#xff0c;可以把 RWMutex 理解为一把读锁加一把写锁&#xff1b; 写锁具有严格的排他性&…

【python】OpenCV—Extreme Points in the Contour

文章目录 1、需求描述2、功能实现3、更多的例子4、完整代码5、参考 1、需求描述 给一张图片&#xff0c;找出其轮廓&#xff0c;并画出轮廓的上下左右极值点 输入图片 输出效果 2、功能实现 # 导入必要的包 import imutils import cv2 # 加载图像&#xff0c;将其转换为灰度…

vue3 + antd vue 纯前端 基于xlsx 实现导入excel 转 json,将json数据转换XLSX并下载(下载模版)

一、导入 0、关键代码 // 安装插件 npm i xlsx/yarn add xlsx // 导入xlsx import * as XLSX from xlsx; 点击提交的时候才整理数据。上传的时候文件保存在 state.form.file[0] 中的 // 定义字段映射关系 const fieldMap {sheet2json: {技能名称: skill_name,技能等级: …

uni-app 影视类小程序开发从零到一 | 开源项目分享

引言 在数字娱乐时代&#xff0c;移动设备已成为我们生活中不可或缺的一部分&#xff0c;尤其是对于电影爱好者而言&#xff0c;随时随地享受精彩影片成为一种日常需求。爱影家&#xff0c;一款基于 uni-app 开发的影视类小程序&#xff0c;正是为此而生。它不仅提供了丰富的影…

【Django+Vue3 线上教育平台项目实战】购物车与订单模块的精简实现与数据安全策略

文章目录 前言一、购物车模块1.后端核心逻辑2.前端页面代码3.操作流程及演示 二、订单模块1.订单模块模型类设计1.展示订单信息a.页面展示b.前端核心代码c.后端核心逻辑 2.订单是否使用优惠券与积分a.页面展示b.前端核心代码 3.订单支付方式a.页面展示b.前端核心代码 4.提交订单…

PyTorch Autograd内部实现

原文&#xff1a; 克補 爆炸篇 25s (youtube.com) 必应视频 (bing.com)https://www.bing.com/videos/riverview/relatedvideo?&qPyTorchautograd&qpvtPyTorchautograd&mid1B8AD76943EFADD541E01B8AD76943EFADD541E0&&FORMVRDGAR 前面只要有一个node的re…

北京交通大学《深度学习》专业课,实验3卷积、空洞卷积、残差神经网络实验

一、实验要求 1. 二维卷积实验&#xff08;平台课与专业课要求相同&#xff09; ⚫ 手写二维卷积的实现&#xff0c;并在至少一个数据集上进行实验&#xff0c;从训练时间、预测精 度、Loss变化等角度分析实验结果&#xff08;最好使用图表展示&#xff09; ⚫ 使用torch.nn…

Matlab基础语法篇(下)

Matlab基础语法&#xff08;下&#xff09; 一、逻辑基础&#xff08;一&#xff09;逻辑运算符&#xff08;二&#xff09;all、any、find函数&#xff08;三&#xff09;练习 二、结构基础&#xff08;一&#xff09;条件结构&#xff08;1&#xff09;if-elseif-else-end&am…

十、操作符详解

目录 1、操作符分类 2、二进制转换 2.1二进制转十进制 2.1.1、十进制转二进制 2.2、二进制转八进制和十六进制 2.2.1、二进制转八进制 2.2.2、二进制转十六进制 3、原码、反码、补码 4、移位操作符&#xff08;移动的是二进制位&#xff09; 4.1、左移操作符 4.2、右…

VMware虚拟机下安装Ubuntu(详细教程,最小系统的安装,含VMware Tools)

1.VM的下载安装 VMware的下载安装教程_vm16 pro下载-CSDN博客 2. Ubuntu 下载 在官网或者镜像站下载所需版本的.ios镜像&#xff0c;这个镜像在接下来的步骤中会用到&#xff1a; Ubuntu 22.04.4 LTS 下载 和 清华大学开源软件镜像站 - Ubuntu 22.04.4 下载 3. 创建虚拟机 […

【C语言】深入解析希尔排序

文章目录 什么是希尔排序&#xff1f;希尔排序的基本实现代码解释希尔排序的优化希尔排序的性能分析希尔排序的实际应用结论 在C语言编程中&#xff0c;希尔排序是一种高效的排序算法&#xff0c;是插入排序的一种更高效的改进版本。它通过比较相距一定间隔的元素来进行排序&am…

【STM32嵌入式系统设计与开发---拓展】——1_10矩阵按键

这里写目录标题 1、矩阵按键2、代码片段分析 1、矩阵按键 通过将4x4矩阵按键的每一行依次设为低电平&#xff0c;同时保持其它行为高电平&#xff0c;然后读取所有列的电平状态&#xff0c;可以检测到哪个按键被按下。如果某列变为低电平&#xff0c;说明对应行和列的按键被按下…