【数据结构】双向链表(链表实现+测试+原码)

前言

在双向链表之前,如果需要查看单链表来复习一下,链接在这里:

http://t.csdnimg.cn/Ib5qS

1.双向链表


1.1 链表的分类

实际中链表的结构非常多样,以下情况组合起来就有8种链表结构:

1.1.1 单向或者双向

1.1.2 带头或者不带头

1.1.3 循环或者非循环

虽然有这么多的链表的结构,但是我们实际中最常用还是两种结构:

1. 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。

2. 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了,今天我们就来实现这种代码。

1.2 双向链表的实现

DList.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "DList.h"LTNode* BuyLTNode(LTDataType x)
{LTNode* node = (LTNode*)malloc(sizeof(LTNode));if (node == NULL){perror("Malloc fail");exit(-1);}node->data = x;node->next = NULL;return node;
}
LTNode* LTInit()
{LTNode* phead  = BuyLTNode(-1);phead->next = phead;phead->prev = phead;return phead;
}void LTPrint(LTNode * phead)
{assert(phead);printf("phead<=>");LTNode* cur = phead->next;while (cur != phead){printf("%d<=>", cur->data);cur = cur->next;}printf("\n");
}void LTPushBack(LTNode* phead, LTDataType x)
{assert(phead);//LTNode* tail = phead->prev;//LTNode* newnode = BuyLTNode(x);//newnode->prev = tail;//tail->next = newnode;//newnode->next = phead;//phead->prev = newnode;LTInsert(phead->prev, x);}void LTPopBack(LTNode* phead)
{LTNode* del = NULL;//assert(phead);//if (phead->prev != phead)//链表指向自己,说明为空//{//	del = phead->prev;//	phead->prev = phead->prev->prev;//	phead->prev->next = phead;//}//else//	printf("链表为空,无需尾删");//free(del);LTErase(phead->prev);
}void LTPushFront(LTNode* phead, LTDataType x)
{assert(phead);//newnode->next = phead->next;	//先改变新插入的值,以免链表断开//newnode->prev = phead;//phead->next->prev = newnode;	//改变原本第二个节点的值//phead->next = newnode;			//改变为第一个节点//更稳妥的办法:双指针//LTNode* newnode = BuyLTNode(x);//LTNode* first = phead->next;//phead->next = newnode;//newnode->prev = phead;//newnode->next = first;//first->prev = newnode;LTInsert(phead->next, x);
}
//头删
void LTPopFront(LTNode* phead)
{assert(phead);assert(phead->next != phead);//LTNode* first = phead->next;//LTNode* second = first->next;//free(first);//phead->next = second;//second->prev = phead;LTErase(phead->next);
}int LTSize(LTNode* phead)
{assert(phead);int size = 0;LTNode* cur = phead->next;while (cur != NULL){size++;cur = cur->next;}return size;
}void LTInsert(LTNode* pos, LTDataType x)
{assert(pos);LTNode* posPrev = pos->prev;LTNode* newnode = BuyLTNode(x);posPrev->next = newnode;newnode->prev = posPrev;newnode->next = pos;pos->prev = newnode;}
//删除pos位置
void LTErase(LTNode* pos)
{assert(pos);LTNode* posPrev = pos->prev;LTNode* posNext = pos->next;free(pos);posPrev->next = posNext;posNext->prev = posPrev;
}//寻找值
LTNode* LTFind(LTNode* phead, LTDataType x)
{assert(phead);assert(phead->next);LTNode* pos = phead->next;while (pos){if (pos->data == x){return pos;}pos = pos->next;}
}//删除表
void LTDestroy(LTNode* phead)
{assert(phead);LTNode* cur = phead->next;while (cur != phead){LTNode* next = cur->next;free(cur);cur = next;}
}

DList.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>typedef int LTDataType;
typedef struct ListNode
{struct ListNode* next;struct ListNode* prev;LTDataType data;
}LTNode;
//申请空间
LTNode* BuyLTNode(LTDataType x);
//初始化指针
LTNode* LTInit();
//打印
void LTPrint(LTNode* phead);
//尾插
void LTPushBack(LTNode* phead, LTDataType x);
//尾删
void LTPopBack(LTNode* phead);
//头插
void LTPushFront(LTNode* phead, LTDataType x);
//头删
void LTPopFront(LTNode* phead);
//记录个数
int LTSize(LTNode* phead);
//pos之前插入
void LTInsert(LTNode* pos, LTDataType x);
//删除pos位置
void LTErase(LTNode* pos);
//寻找值
LTNode* LTFind(LTNode* phead, LTDataType x);
//删除表
void LTDestroy(LTNode* phead);

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "DList.h"void TestList1()
{LTNode* plist = NULL;plist = LTInit();LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPushBack(plist, 4);LTPushBack(plist, 5);LTPrint(plist);LTPopBack(plist);LTPrint(plist);LTPushFront(plist, 99);LTPrint(plist);LTPopFront(plist);LTPrint(plist);LTNode* testlist = LTFind(plist, 5);LTPrint(testlist);}
int main()
{TestList1();}

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

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

相关文章

技术精英求职必备:Android开发工程师简历制作全指南

简历编写核心原则 撰写针对安卓开发工程师职位的简历时&#xff0c;关键在于准确展示您在使用Android SDK进行应用开发、界面设计和性能优化方面的专业技能、项目经验和技术成就。简历应突出您的Android编程能力、对Kotlin和Java的熟练运用&#xff0c;以及在移动应用开发领域…

【开源】JAVA+Vue.js实现车险自助理赔系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 角色管理模块2.3 车辆档案模块2.4 车辆理赔模块2.5 理赔照片模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 角色表3.2.2 车辆表3.2.3 理赔表3.2.4 理赔照片表 四、系统展示五、核心代码5.1 查询车…

《Django+React前后端分离项目开发实战:爱计划》 01 项目整体概述

01 Introduction 《Django+React前后端分离项目开发实战:爱计划》 01 项目整体概述 Welcome to Beginning Django API wih React! This book focuses on they key tasks and concepts to get you started to learn and build a RESTFul web API with Django REST Framework,…

ubuntu22.04@laptop OpenCV Get Started: 006_annotating_images

ubuntu22.04laptop OpenCV Get Started: 006_annotating_images 1. 源由2. line/circle/rectangle/ellipse/text 应用Demo3 image_annotation3.1 C应用Demo3.2 Python应用Demo3.3 重点过程分析3.3.1 划线3.3.2 画圆3.3.3 矩形3.3.4 椭圆3.3.5 文字 4. 总结5. 参考资料 1. 源由 …

mysql索引的概念以及数据结构

索引的概念&#xff1a; 目的和作用&#xff1a; MySQL索引是一种数据结构&#xff0c;用于加速数据库查询操作。它类似于书籍的目录&#xff0c;可以快速定位到所需的数据&#xff0c;而不必全表扫描。 工作原理&#xff1a; 当你在表上创建索引时&#xff0c;MySQL会在索引中…

MySQL篇----第二十篇

系列文章目录 文章目录 系列文章目录前言一、NULL 是什么意思二、主键、外键和索引的区别?三、你可以用什么来确保表格里的字段只接受特定范围里的值?四、说说对 SQL 语句优化有哪些方法?(选择几条)前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍…

Nginx实战:1-安装搭建

目录 前言 一、yum安装 二、编译安装 1.下载安装包 2.解压 3.生成makefile文件 4.编译 5.安装执行 6.执行命令软连接 7.Nginx命令 前言 nginx的安装有两种方式&#xff1a; 1、yum安装&#xff1a;安装快速&#xff0c;但是无法在安装的时候带上想要的第三方包 2、…

微软 CMU - Tag-LLM:将通用大语言模型改用于专业领域

文章目录 一、前言二、主要内容三、总结 &#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、前言 论文地址&#xff1a;https://arxiv.org/abs/2402.05140 Github 地址&#xff1a;https://github.com/sjunhongshen/Tag-LLM 大语言模型&#xff08…

MYSQL分区NOW()不支持

传说同事写个复杂的SQL代码,跑一次需要7-10秒, 复杂如上,我也懒得去分析 IF IF IF是怎么回事了! 发现此表是分区表,后面要求加上了分区时间,以便利用到分区裁剪技术. 因为需求是查近10天来到期还款的人和金额.就是今天应该还款的人, 一般还款周期是7天. 给个10天的范围挺可以的…

从零开始学howtoheap:fastbins的double-free攻击实操1

how2heap是由shellphish团队制作的堆利用教程&#xff0c;介绍了多种堆利用技术&#xff0c;后续系列实验我们就通过这个教程来学习。环境可参见从零开始配置pwn环境&#xff1a;优化pwn虚拟机配置支持libc等指令-CSDN博客 1.fastbins的double-free攻击 下面的程序展示了fast…

计算机网络——07协议层次及服务模型

协议层次及服务模型 协议层次 网络是一个复杂的系统 网络功能复杂&#xff1a;数字信号的物理信号承载、点到点、路由、rdt、进程区分、应用等现实来看&#xff0c;网络的许多构成元素和设备&#xff1a; 主机路由器各种媒体的链路应用协议硬件&#xff0c;软件 问题是&am…

openJudge | 距离排序

总时间限制: 1000ms 内存限制: 65536kB 描述 给出三维空间中的n个点&#xff08;不超过10个&#xff09;,求出n个点两两之间的距离,并按距离由大到小依次输出两个点的坐标及它们之间的距离。 输入 输入包括两行&#xff0c;第一行包含一个整数n表示点的个数&#xff0c;第二…

2024年华为OD机试真题-英文输入法-Java-OD统一考试(C卷)

题目描述: 主管期望你来实现英文输入法单词联想功能。需求如下: 依据用户输入的单词前缀,从已输入的英文语句中联想出用户想输入的单词,按字典序输出联想到的单词序列,如果联想不到,请输出用户输入的单词前缀。 注意: 1. 英文单词联想时,区分大小写 2. 缩略形式如”d…

springboot redis 实现消息队列

在Spring Boot中使用Redis作为消息队列&#xff0c;可以通过以下步骤实现&#xff1a; 1. 添加依赖 在pom.xml文件中添加Spring Boot Redis和Jedis的依赖&#xff1a; xml <dependencies> <!-- Spring Boot Redis --> <dependency> <g…

32MPU6050

MPU6050无SPI相关电路 硬件电路 ​编辑 MEMS说公司研发的微机电系统&#xff0c;可以用电子的方案进行姿态测量 芯片内部含有自由落体检测&#xff0c;运动检测和零运动检测 时钟源&#xff1a;内部晶振&#xff0c;陀螺仪晶振和外部时钟引脚的方波 运动检测有高通滤波器可…

原语,原子,线程安全

原子操作和原语是计算机科学中常见的概念&#xff0c;通常用于多线程或多进程环境中&#xff0c;以确保数据的一致性和同步。 原子操作&#xff08;Atomic Operations&#xff09; 原子操作是不可再分的操作&#xff0c;在执行完毕之前不会被线程调度系统中断的操作。从外部看…

「递归算法」:反转链表

一、题目 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1]示例 2&#xff1a; 输入&#xff1a;head [1,2] 输出&#xff1a;[2,1]示例 3&#xff1a…

提升幸福感,中国的龙!理性看待个人发声——早读

打了过年球&#xff0c;爽&#xff01; 引言代码第一篇 人民日报 【夜读】新的一年&#xff0c;提升幸福感的6件小事第二篇 茶百道的广告文第三篇 人民日报 热搜第一&#xff01;《山河诗长安》&#xff0c;太燃了第四篇 人民日报 中国有真龙第五篇 人民日报 来啦 新闻早班车要…

C++ dfs 的状态表示(五十一)【第十一篇】

今天我们接着学习dfs&#xff08;状态表示&#xff09;。 1.抽象形式的dfs 前面用到的 DFS 算法都是比较容易想象出搜索过程的&#xff0c;接下来我们看一些不那么容易想象搜索过程的 DFS 过程&#xff0c;这些问题我们称为抽象形式的 DFS。 来回顾一下上节课遇到的一个问题&a…

vue对于安装依赖时不好习惯的反省

因为一个不好的习惯&#xff0c;我总是喜欢–save去安装依赖包&#xff0c;然后发现最后打包后的内容总是很大。就想着怎么能让包小一些&#xff0c;就发现我遗漏了vue安装依赖的一个小知识点 安装依赖的时候可以-s -d -g去安装&#xff0c;要根据使用的内容选择去安装&#xf…