【数据结构 05】双链表

一、原理

双链表又称双向链表,通常情况下是带头循环结构,在C++STL标准模板库中封装的<list.h>头文件就是带头双向循环链表。

特性:增删灵活且高效,支持随机增删但不支持随机访问

设计思路:

  1. 链表包含一个头节点head,不存储数据,用于链表的维护,提高数据增删效率
  2. 每一个链表节点Node都包含一个数据和两个指针(前驱指针prev和后继指针next)
  3. 前驱指针prev指向前一个节点,后继指针next指向后一个节点
  4. 当链表为空时,头结点head的prev指针和next指针都指向head自身
  5. 节点的增删通过前后指针指向的改变即可完成,无需数据移动,效率高

二、DoubleList.h

#define _CRT_SECURE_NO_WARNINGS 1#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>typedef int DataType;typedef struct Node
{DataType data;struct Node* next;struct Node* prev;
}Node;typedef struct List
{Node* head;
}List;void Init(List* plist)
{plist->head = (Node*)malloc(sizeof(Node));plist->head->prev = plist->head;plist->head->next = plist->head;
}bool Empty(List* plist)
{return plist->head == plist->head->next;
}Node* BuyNode(DataType x)
{Node* node = (Node*)malloc(sizeof(Node));node->data = x;node->next = NULL;node->prev = NULL;
}void PushFront(List* plist, DataType x)
{Node* node = BuyNode(x);if (Empty(plist)){node->next = plist->head;node->prev = plist->head;plist->head->next = node;plist->head->prev = node;}else{Node* next = plist->head->next;node->prev = plist->head;node->next = next;next->prev = node;plist->head->next = node;}
}void PushBack(List* plist, DataType x)
{Node* node = BuyNode(x);if (Empty(plist)){node->next = plist->head;node->prev = plist->head;plist->head->next = node;plist->head->prev = node;}else{Node* prev = plist->head->prev;node->next = plist->head;node->prev = prev;prev->next = node;plist->head->prev = node;}
}void PopFront(List* plist)
{if (Empty(plist)){printf("双链表为空,头删失败\n");return;}Node* cur = plist->head->next;plist->head->next = cur->next;cur->next->prev = plist->head;free(cur);cur = NULL;
}void PopBack(List* plist)
{if (Empty(plist)){printf("双链表为空,尾删失败\n");return;}Node* cur = plist->head->prev;plist->head->prev = cur->prev;cur->prev->next = plist->head;free(cur);cur = NULL;
}Node* Find(List* plist, DataType x)
{Node* cur = plist->head->next;while (cur != plist->head){if (cur->data == x)return cur;cur = cur->next;}return NULL;
}void InsertFront(Node* pos, DataType x)
{if (pos == NULL){printf("pos为空,插入失败\n");return;}Node* node = BuyNode(x);Node* prev = pos->prev;prev->next = node;node->prev = prev;node->next = pos;pos->prev = node;
}void Delete(Node* pos)
{if (pos == NULL){printf("pos为空,Delete失败\n");return;}Node* next = pos->next;Node* prev = pos->prev;next->prev = prev;prev->next = next;free(pos);pos = NULL;
}void Destroy(List* plist)
{while (!Empty(plist)){PopFront(plist);}free(plist->head);plist->head = NULL;printf("双链表销毁成功\n");
}void Print(List* plist)
{if (plist->head == NULL){printf("双链表不存在\n");return;}Node* cur = plist->head->next;printf("head -> ");while (cur != plist->head){printf("%2d -> ", cur->data);cur = cur->next;}printf("head\n");
}

三、test.c

#define _CRT_SECURE_NO_WARNINGS 1#include "DoubleList.h"int main()
{List list;Init(&list);Print(&list);	// head -> head// 尾插数据PushBack(&list, 1);PushBack(&list, 3);PushBack(&list, 5);PushBack(&list, 7);Print(&list); // head -> 1 -> 3 -> 5 -> 7 -> head// 头插数据PushFront(&list, 2);PushFront(&list, 4);PushFront(&list, 6);PushFront(&list, 8);Print(&list); // head -> 8 -> 6 -> 4 -> 2 -> 1 -> 3 -> 5 -> 7->head// 尾删数据PopBack(&list);PopBack(&list);PopBack(&list);Print(&list); // head -> 8 -> 6 -> 4 -> 2 -> 1 -> head// 头删数据PopFront(&list);PopFront(&list);PopFront(&list);Print(&list); // head -> 2 -> 1 -> head// 在查询的节点前插入数据InsertFront(Find(&list, 1), 11);InsertFront(Find(&list, 11), 111);Print(&list); // head -> 2 -> 111 -> 11 -> 1 -> head// 删除查询的节点Delete(Find(&list, 1));Delete(Find(&list, 11));Delete(Find(&list, 111));Print(&list); // head -> 2 -> head// 销毁链表Destroy(&list); // 链表销毁成功Print(&list); // 链表不存在return 0;
}

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

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

相关文章

【Linux】模拟实现一个简单的minishell

目录 从显示屏获取输入字符流 分割字符串 取出命令名称及选项 去除输入时多按的那个换行符 创建子进程&#xff0c;实现程序替换 如果替换失败&#xff0c;进程终止exit 查看子进程情况 实现echo $?功能 实现cd 最终代码 基本思路 让父进程创建一个子进程&#xff0c…

[NCTF2019]Fake XML cookbook(特详解)

先试了一下弱口令&#xff0c;哈哈习惯了 查看页面源码发现xml function doLogin(){var username $("#username").val();var password $("#password").val();if(username "" || password ""){alert("Please enter the usern…

CISAW和CISP-PTE证书选择指南

&#x1f4e3;在信息安全领域&#xff0c;选择合适的证书可以为你的职业生涯增添光彩。很多从事信息渗透行业的朋友经常讨论CISP-PTE和CISAW之间的选择问题。今天就从4个方面带你详细了解这两张证书&#xff0c;帮你做出明智的选择&#xff01; 1️⃣证书的行业前景 &#x1f4…

【Nuxt3】layouts的使用

简言 Nuxt 提供了一个布局框架&#xff0c;用于将常见的 UI 模式提取为可重用的布局。 为了获得最佳性能&#xff0c;在使用时&#xff0c;放置在此目录中的组件将通过异步导入自动加载。 layouts layouts文件夹存放的是ui布局文件&#xff0c;就是实现一个页面整体架构规则的…

超声波风速风向仪的工作原理

TH-WQX2在我们的日常生活中&#xff0c;气象条件的影响无处不在。无论是准备户外活动&#xff0c;还是安排农业生产&#xff0c;了解当天的风速和风向都是非常关键的。随着科技的发展&#xff0c;超声波风速风向仪的出现为气象监测带来了革命性的变化。 一、超声波风速风向仪的…

聚合支付,实现支付宝微信扫二维码直接跳转支付

具体要实现的功能&#xff1a;手机支付宝或微信扫描同一个二维码&#xff0c;跳转各自的支付 微信使用&#xff1a;jsapi支付 支付宝&#xff1a;wappay 上篇已写了如何实现内网穿透调试就不多叙述 1.判断客户端类型&#xff0c;从request的中将user-agent拉取下来&#xf…

【Javaweb】【C00157】基于SSM的宠物护理预定系统(论文+PPT)

基于SSM的宠物护理预定系统&#xff08;论文PPT&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于ssm的宠物护理预订系统 本系统分为前台系统模块、后台管理员模块以及后台会员用户模块 其中前台系统模块&#xff1a;当游客打开系统的网址后&…

报错找不到msvcp140.dll怎么办?msvcp140.dll缺失的详细修复指南

在计算机系统运行过程中&#xff0c;如果出现msvcp140.dll文件丢失的情况&#xff0c;可能会引发一系列显著的问题和故障。首先&#xff0c;我们需要理解msvcp140.dll究竟是什么以及它在操作系统中扮演何种角色。msvcp140.dll是一个动态链接库&#xff08;DLL&#xff09;文件&…

在线版XD,免费使用,功能全面,设计神器!

Adobe XD是什么软件&#xff1f; Adobe XD软件是一个结合设计和建立原型功能的一站式UX/UI设计平台。在XD软件中&#xff0c;数字团队可以进行移动应用、网页设计和原型制作。与此同时&#xff0c;Adobe XD软件也是一种跨平台设计产品&#xff0c;结合设计和建立原型功能&…

Android悬浮窗实现步骤

最近想做一个悬浮窗秒表的功能&#xff0c;所以看下悬浮窗具体的实现步骤 1、初识WindowManager 实现悬浮窗主要用到的是WindowManager SystemService(Context.WINDOW_SERVICE) public interface WindowManager extends ViewManager {... }WindowManager是接口类&#xff0c…

MySQL-窗口函数

介绍&#xff1a; MSQL8.0新增窗口函数商口函数又被称为开窗函数&#xff0c;与Oracle窗口函数类似&#xff0c;属于MysaL的一大特点 非聚合窗口函数是相对于聚函数来说的。聚合函数是对一组数据计算后返回单个值(即分组)&#xff0c;非聚合函数一次只会处理一行数据。窗口聚…

盲盒小程序开发,实现“双收益”

盲盒在我国是一个发展潜力较高的市场&#xff0c;盲盒具有的刺激和收藏价值&#xff0c;深受消费者的喜爱&#xff0c;盲盒的“隐藏款”机制&#xff0c;能够为消费者带来惊喜感。盲盒一般与影视动漫IP合作&#xff0c;推出盲盒商品&#xff0c;这也是深受年轻人追捧的一大特点…

Redis内存设置

通过redis-cli进入Redis命令行 redis权限认证命令&#xff1a;auth 查看redis内存使用情况的命令&#xff1a;info memory 查看最大内存命令&#xff1a;config get maxmemory 设置最大内存命令&#xff1a;config set maxmemory 也可以通过redis.conf配置文件修改最大内存…

Cache Lab:Part A【模拟出使用LRU策略的高速缓存存储器组织结构】

目录 任务描述 知识回顾 实验内容 测试结果 Cache Lab 对应《CS:APP》6.3节至第六章结束的内容。 任务描述 Your job for Part A is to fill in the csim.c file so that it takes the same command line arguments and produces the identical output as the reference …

MySQL事务和SQL优化

目录 1 什么是事务 2 事务的特征 3 MySQL使用事务 实现 示例 4 事务的隔离级别 幻读 解决方法 脏读 不可重复读 幻读和不可重复读两者区别 事物的隔离级别 5 数据库优化 5.1 影响性能因素的优化 服务优化 应用优化 5.2 谁参与优化 5.3 系统优化 软件优化 硬件优…

人力RPO蓝海项目可靠性有多大?

随着全球经济的快速发展&#xff0c;人力资源外包服务逐渐成为企业降低成本、提高效率的重要手段。其中&#xff0c;RPO(招聘流程外包)作为人力资源外包的一种形式&#xff0c;日益受到企业的青睐。然而&#xff0c;对于RPO的可靠性&#xff0c;业界和学界存在不同的看法。本文…

宏景eHR FrCodeAddTreeServlet SQL注入漏洞复现

前言 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该文章仅供学习用途使用。 一、产…

mybatisplus-多数据源配置

1. 流程 pom文件yml配置多数据源具体服务添加注解DS(“***”) 1.pom文件 <!--mybatis plus 起步依赖--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.0</vers…

万户 ezOFFICE DocumentEditExcel.jsp SQL注入漏洞

0x01 产品简介 万户OA ezoffice是万户网络协同办公产品多年来一直将主要精力致力于中高端市场的一款OA协同办公软件产品,统一的基础管理平台,实现用户数据统一管理、权限统一分配、身份统一认证。统一规划门户网站群和协同办公平台,将外网信息维护、客户服务、互动交流和日…

STM32F407移植OpenHarmony笔记6

继上一篇笔记&#xff0c;编译好STM32的裸机程序&#xff0c;能点亮LED灯了。 下一步就是启动liteos_m内核了。 不过为了更好的调试代码&#xff0c;需要先把printf重定向到串口&#xff0c;基于gcc的printf重定向和Keil不一样。 直接新建printf.c&#xff0c;在里面重写printf…