数据结构—C语言实现双向链表

目录

1.双向带头循环链表

2.自定义头文件:

3.List.cpp 文件

 3.1 newnode()函数讲解

3.2 init() 函数 初始化

3.3 pushback()函数 尾插

3.4 pushfront()函数 头插

3.5 popback() 尾删

3.6 popfront() 函数 头删

3.7 insert()函数 在pos之后插入

3.8 popback()函数 删除

3.9 find() 函数 查找

3.10 print()函数 打印

4.test.cpp 文件


1.双向带头循环链表

结构:

 

2.自定义头文件:

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<stdlib.h>
#include<string>
using namespace std;typedef int type;struct List
{type val;struct List* pre;struct List* next;
};typedef struct List List;void init(List** st);
List* newnode(type x);
void pushback(List* st, type x);
void print(List* st);
void pushfront(List* st, type x);
void popback(List* st);
void popfront(List* st);
void insert(List* pos, type x);
void erase(List* pos);
List* find(List* st, type x);
void destory(List* st);
void menu();

双向链表中的结点具有pre和next指针,分别连向上一个结点和下一个结点,val用来存储值。

3.List.cpp 文件

代码:

#include"Sqlist.h"void menu()
{printf("******************************\n");printf("***1.init        2.pushback***\n");printf("***3.pushfront      4.print***\n");printf("***5.popback     6.popfront***\n");printf("***7.insert         8.erase***\n");printf("***9.destory         0.exit***\n");printf("******************************\n");
}void init(List** st)
{*st = newnode(-1);
}
List* newnode(type x)
{List* nnee = (List*)malloc(sizeof(List));if (nnee == NULL){perror("malloc");exit(0);}nnee->val = x;nnee->next = nnee->pre = nnee;return nnee;
}
void pushback(List* st, type x)
{if (st == NULL){printf("st is NULL\n");return;}List* nnee = newnode(x);nnee->next = st;nnee->pre = st->pre;st->pre->next = nnee;st->pre = nnee;}void print(List* st)
{List* cur = st->next;while (cur != st){cout << cur->val << ' ';cur = cur->next;}cout << endl;return;
}void pushfront(List* st, type x)
{if (st == NULL){printf("st is NULL\n");return;}List* nnee = newnode(x);nnee->next = st->next;nnee->pre = st;st->next->pre = nnee;st->next = nnee;}void popback(List* st)
{if (st == NULL){printf("st is NULL\n");return;}if (st->next == st){printf("st is empty\n");return;}List* cur = st->pre;cur->pre->next = st;st->pre = cur->pre;free(cur);cur = NULL;}
void popfront(List* st)
{if (st == NULL){printf("st is NULL\n");return;}if (st->next == st){printf("st is empty\n");return;}List* del = st->next;st->next = del->next;del->next->pre = st;free(del);del = NULL;}void insert(List* pos, type x)//之后
{if (pos == NULL){printf("NULL\n");return;}List* nnee = newnode(x);nnee->next = pos->next;nnee->pre = pos;pos->next->pre = nnee;pos->next = nnee;
}
void erase(List* pos)
{if (pos == NULL){printf("pos is NULL\n");return;}pos->pre->next = pos->next;pos->next->pre = pos->pre;free(pos);pos = NULL;
}
List* find(List* st, type x)
{List* cur = st->next;while (cur != st){if (cur->val == x){return cur;}cur = cur->next;}return NULL;
}void destory(List* st)
{if (st == NULL){printf("st is NULL\n");return;}List* cur = st->next;while (cur != st){List* ne = cur->next;free(cur);cur = ne;}free(st);st = NULL;cur = NULL;}

 

 3.1 newnode()函数讲解

代码:

List* newnode(type x)
{List* nnee = (List*)malloc(sizeof(List));if (nnee == NULL){perror("malloc");exit(0);}nnee->val = x;nnee->next = nnee->pre = nnee;return nnee;
}

(1).使用malloc函数开辟一块空间,赋给nnee。

(2).再判断是否开辟成功。开辟成功后,将x赋值给nnee的val,并且把nnee的两个指针域都赋值为自己。最后返回该结点。

3.2 init() 函数 初始化

void init(List** st)
{*st = newnode(-1);
}

(1).由于我们创建的是带头循环链表,所以初始化要将链表的最开始创建一个头结点。

3.3 pushback()函数 尾插

void pushback(List* st, type x)
{if (st == NULL){printf("st is NULL\n");return;}List* nnee = newnode(x);nnee->next = st;nnee->pre = st->pre;st->pre->next = nnee;st->pre = nnee;
}

(1).先判断链表的地址是否为空。

(2).创建一个新结点。

(3).将新结点的next指针指向头结点,再将新结点的pre指针指向st的pre。

再将头结点的pre的next(链表最后一个结点)指向新结点,再将头结点的pre指向新结点。

3.4 pushfront()函数 头插

void pushfront(List* st, type x)
{if (st == NULL){printf("st is NULL\n");return;}List* nnee = newnode(x);nnee->next = st->next;nnee->pre = st;st->next->pre = nnee;st->next = nnee;}

(1).创建新结点。

(2).将新结点的next指向头结点的next,再将新结点的pre指向头结点。

(3).再将头结点的next的pre指向新结点。头结点的next指向新结点。

3.5 popback() 尾删

void popback(List* st)
{if (st == NULL){printf("st is NULL\n");return;}if (st->next == st){printf("st is empty\n");return;}List* cur = st->pre;cur->pre->next = st;st->pre = cur->pre;free(cur);cur = NULL;}

(1).首先判断链表是否有头结点,还要判断链表是否已经为空,为空则 st->next == st,头结点自己指向自己时

(2).创建一个指针cur,令cur指向链表最后一个结点,再令最后一个节点的pre(倒数第二个结点)的next指向头结点,再令头节点的pre指向cur的pre(倒数第二个指针)。

3.6 popfront() 函数 头删

void popfront(List* st)
{if (st == NULL){printf("st is NULL\n");return;}if (st->next == st){printf("st is empty\n");return;}List* del = st->next;st->next = del->next;del->next->pre = st;free(del);del = NULL;}

(1).首先判断链表是否有头结点,还要判断链表是否已经为空,为空则 st->next == st,头结点自己指向自己时

(2).创建一个指针del,令del指向头结点的next(头结点的下一个结点),再将头结点的next指向del的next,再将del的next的pre指向头结点。

3.7 insert()函数 在pos之后插入

void insert(List* pos, type x)//之后
{if (pos == NULL){printf("NULL\n");return;}List* nnee = newnode(x);nnee->next = pos->next;nnee->pre = pos;pos->next->pre = nnee;pos->next = nnee;
}

 (1).创建一个新结点,令新结点的next指向pos的next。再将新结点的pre指向pos。

(2).再将pos的next的pre(pos下一个结点的pre指针)指向新结点;pos的next指向新结点。

 

3.8 popback()函数 删除

void erase(List* pos)
{if (pos == NULL){printf("pos is NULL\n");return;}pos->pre->next = pos->next;pos->next->pre = pos->pre;free(pos);pos = NULL;
}

(1).将pos的pre的next(pos的前一个节点的next指针)指向pos的next(pos的下一个节点)。

(2).再将pos的next的pre(pos的下一个节点的pre指针)指向pos的pre(pos的前一个指针) 

 

 

3.9 find() 函数 查找

List* find(List* st, type x)
{List* cur = st->next;while (cur != st){if (cur->val == x){return cur;}cur = cur->next;}return NULL;
}

(1).直接遍历链表即可,当遇到当前节点的val与x相同时,直接返回地址。

(2).若遍历完后还没有找到,则最后返回空。

3.10 print()函数 打印

void print(List* st)
{List* cur = st->next;while (cur != st){cout << cur->val << ' ';cur = cur->next;}cout << endl;return;
}

(1).直接遍历链表即可,依次打印节点的每个值。

4.test.cpp 文件

代码:

#include"Sqlist.h"int main()
{List* head;List* pos=NULL;type x;int op;int n;type y;init(&head);do{menu();printf("input optio\n");cin >> op;switch (op){case 1:init(&head);break;case 2:printf("input you want push number\n");cin >> n;for (int i = 0; i < n; i++){cin >> x;pushback(head, x);}break;case 3:printf("input you want push number\n");cin >> n;for (int i = 0; i < n; i++){cin >> x;pushfront(head, x);}break;case 4:print(head);break;case 5:popback(head);break;case 6:popfront(head);break;case 7:printf("input you pos and val\n");cin >> y >> x;pos = find(head,y);if (pos == NULL){printf("pos is not save\n");}else{insert(pos, x);}break;case 8:printf("input you pos \n");cin >> y;pos = find(head, y);if (pos == NULL){printf("pos is not save\n");}else{erase(pos);}break;case 9:destory(head);break;case 0:break;default:printf("piease input correct option\n");break;}} while (op);}

完. 

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

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

相关文章

uniapp 对接 Apple 登录

由于苹果要求App使用第三方登录必须要求接入Apple登录 不然审核不过 所以&#xff1a; 一、勾选苹果登录 二、 设置AppId Sign In Apple 设置完成重新生成描述文件 &#xff01;&#xff01;&#xff01;&#xff01;证书没关系 示例代码&#xff1a; async appleLogin…

Delta lake with Java--将数据保存到Minio

今天看了之前发的文章&#xff0c;居然有1条评论&#xff0c;看到我写的东西还是有点用。 今天要解决的问题是如何将 Delta产生的数据保存到Minio里面。 1、安装Minio&#xff0c;去官网下载最新版本的Minio&#xff0c;进入下载目录&#xff0c;运行如下命令&#xff0c;曾经…

Co-assistant Networks for Label Correction论文速读

文章目录 Co-assistant Networks for Label Correction摘要方法Noise DetectorNoise Cleaner损失函数 实验结果 Co-assistant Networks for Label Correction 摘要 问题描述&#xff1a; 描述医学图像数据集中存在损坏标签的问题。强调损坏标签对深度神经网络性能的影响。 提…

SpringBoot指标监控

一.SpringBoot指标监控_添加Actuator功能 Spring Boot Actuator可以帮助程序员监控和管理SpringBoot应用&#xff0c;比如健康检查、内存使用情况统计、线程使用情况统计等。我 们在SpringBoot项目中添加Actuator功能&#xff0c;即可使用Actuator监控 项目&#xff0c;用法如…

使用YALMIP定义LMI,SEDUMI求解矩阵方程

YALMIP&#xff08;Yet Another MATLAB Package for Modeling and Optimization&#xff09;是一个MATLAB工具箱&#xff0c;用于定义和求解优化问题&#xff0c;包括线性矩阵不等式&#xff08;LMI&#xff09;问题。SEDUMI是一个用于求解LMI问题的求解器&#xff0c;它可以与…

Vitis HLS 学习笔记--S_AXILITE 寄存器及驱动

目录 1. 简介 2. S_AXILITE Registers 寄存器详解 2.1 “隐式”优势 2.2 驱动程序文件 2.3 硬件头文件 2.4 硬件头文件中 SC/COR/TOW/COH 的解释 2.5 驱动控制过程 3. 总结 1. 简介 回顾此博文《Vitis HLS 学习笔记--Syn Report解读&#xff08;1&#xff09;-CSDN博…

瘦身秘籍:如何使用 PyInstaller 打造超小型 Python 可执行文件

你是否曾经尝试过将你的 Python 程序打包成一个可执行文件&#xff0c;却发现生成的文件大得惊人&#xff1f;别担心&#xff0c;本文将教你如何使用 PyInstaller 尽可能减小生成的 onefile 大小&#xff0c;让你的程序轻盈如风&#xff01; 1. 使用虚拟环境 首先&#xff0c…

Python 与 TensorFlow2 生成式 AI(二)

原文&#xff1a;zh.annas-archive.org/md5/d06d282ea0d9c23c57f0ce31225acf76 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第四章&#xff1a;教授网络生成数字 在前一章中&#xff0c;我们涵盖了神经网络模型的构建基块。在这一章中&#xff0c;我们的第一个项目…

电商技术揭秘四十一:电商平台的营销系统浅析

相关系列文章 电商技术揭秘相关系列文章合集&#xff08;1&#xff09; 电商技术揭秘相关系列文章合集&#xff08;2&#xff09; 电商技术揭秘相关系列文章合集&#xff08;3&#xff09; 文章目录 引言一、用户画像与精准营销用户画像与精准营销的概念用户画像在精准营销中…

正则表达式.java

目录 1.1 正则表达式的概念及演示 正则表达式的作用&#xff1a; 1.2 正则表达式-字符类 1.3 正则表达式-逻辑运算符 1.4 正则表达式-预定义字符 1.5 正则表达式-数量词 1.6 正则表达式练习1 1.7 正则表达式练习2 小结 &#xff1a; ①可以校验字符串是否满足一定的规…

免费通配符证书的申请指南——从申请到启动https

如果您的网站拥有众多二级子域名&#xff0c;那么通配符证书证书是最好的选择。 免费通配符申请流程如下&#xff1a; 1 创建证书服务商账号 首先选择一个提供免费通配符的服务商&#xff0c;打开国产服务商JoySSL官网&#xff0c;创建一个账号&#xff08;注册账号时填写注册…

Android创建快捷方式到桌面

效果图 参考 https://blog.51cto.com/u_16175498/8811197https://blog.51cto.com/u_16175498/8811197 权限 <uses-permission android:name"com.android.launcher.permission.INSTALL_SHORTCUT" /> 实现 if (Build.VERSION.SDK_INT > Build.VERSION_C…

GPG的使用

这里写自定义目录标题 安装加密程序生成加密密钥怎么备份自己的密钥就可以使用公钥加密邮件信息了 安装加密程序 下载gpg4win&#xff1a; https://www.gpg4win.org/index.html 免费的&#xff0c;如果使用的是苹果电脑&#xff0c;使用https://gpgtools.org/。 如果是linux&a…

Python 与 TensorFlow2 生成式 AI(四)

原文&#xff1a;zh.annas-archive.org/md5/d06d282ea0d9c23c57f0ce31225acf76 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第九章&#xff1a;文本生成方法的崛起 在前几章中&#xff0c;我们讨论了不同的方法和技术来开发和训练生成模型。特别是在第六章“使用 …

vue3 依赖-组件tablepage-vue3 项目公共配置封装

github求⭐ 可通过github 地址和npm 地址查看全部内容 vue3 依赖-组件tablepage-vue3说明文档&#xff0c;列表页快速开发&#xff0c;使用思路及范例-汇总 vue3 依赖-组件tablepage-vue3说明文档&#xff0c;列表页快速开发&#xff0c;使用思路及范例&#xff08;Ⅰ&#…

【C++】匿名对象超详细详解(什么是匿名对象?对象可以是哪些类型呢?)

目录 一、前言 二、匿名对象的概念详解 &#x1f95d; 语法结构 &#x1f34d;概念理解 三、匿名对象的对象类型 四、匿名对象的使用 &#x1f347;简单场景的使用 &#x1f349;复杂场景的使用 五、总结 六、共勉 一、前言 在C中&#xff0c;匿名对象&#xff08;Ano…

一文解决ArcGIS生成点和管段 含案例讲解

背景 在工作中&#xff0c;我们经常遇到要将坐标数据导入 GIS&#xff0c;生成点位&#xff0c;若是地理坐标系&#xff08;经纬度&#xff09;&#xff0c;那么直接用 arcgis或者QGIS 导入数据就行了&#xff0c;可实际中总会遇到各种问题&#xff1a; 坐标数据集为大地 200…

如何使用Go语言进行基准测试(benchmark)?

文章目录 一、基准测试的基本概念二、编写基准测试函数三、运行基准测试四、优化代码性能五、注意事项总结 在Go语言中&#xff0c;基准测试&#xff08;benchmark&#xff09;是一种评估代码性能的有效方式。通过基准测试&#xff0c;我们可以测量代码执行的时间、内存使用情况…

【Linux】详解core dump文件的作用以及用法ubuntu20.04下无法形成core dump文件的解决办法

说明 从第三大点开始讲解ubuntu20.04下无法形成core dump文件的解决办法。 一、core与term的区别 在之前讲过的信号中&#xff0c;终止进程的信号的动作分为两种&#xff0c;一种是core&#xff0c;一种是term。term&#xff08;全称termination&#xff09;是直接终止进程&am…

C++ string类

目录 0.前言 1.为什么学习string类 1.1 C语言字符串的局限性 1.2 C string类的优势 2.标准库中的string类 2.1 字符串作为字符序列的类 2.2 接口与标准容器类似 2.3 基于模板的设计 2.4 编码和字符处理 3.string类的常用接口说明 3.1构造函数 3.1.1默认构造函数 3…