数据结构—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,一经查实,立即删除!

相关文章

ES与关系数据库的同步练习(hotel_admin)

目录 1 es与数据库同步的方法2 实践 1 es与数据库同步的方法 方式一&#xff1a;同步调用 优点&#xff1a;实现简单&#xff0c;粗暴缺点&#xff1a;业务耦合度高 方式二&#xff1a;异步通知&#xff08;选择这个折中下&#xff09; 优点&#xff1a;低耦合&#xff0c;…

[C++]11版本新特性4:包装器:function、bind

前言 本文将介绍包装器&#xff08;适配器&#xff09; 引入 我们之前接触过函数指针、仿函数、lambda 但他们各有优劣&#xff0c;有没有一种方法可以对众多类型进行打包封装&#xff0c;这样就可以提高效率了 那就是function包装器 包装器 function 包装器本质是一个类…

汇编语言-jcxz指令和loop指令

jcxz指令&#xff1a; jcxz 是有条件转移指令&#xff0c; 所有的有条件转移指令都是短转移&#xff0c; 在对应的机器码中包含转移的位移&#xff0c;而不是目的地址 对 IP 的修改范围都为&#xff1a; -128-127 指令格式&#xff1a;jcxz 标号 &#xff08;如果 (cx)0 &…

uniapp 对接 Apple 登录

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

Android APP转成launcher

一、背景 使用场景&#xff0c;需要开机的时候&#xff0c;自动启动app&#xff0c;解决方案为将Android app转成 launcher app&#xff0c;可实现效果。 二、实现 在app入口activity 的配置文件&#xff08;AndroidManifest.xml&#xff09;对应位置&#xff0c;添加 <cat…

深入探索DreamFusion:文本到3D生成的革命性技术

深入探索DreamFusion&#xff1a;文本到3D生成的革命性技术 引言&#xff1a; 在人工智能和计算机视觉领域&#xff0c;DreamFusion无疑是一个引人注目的新星。这项技术&#xff0c;基于Google提出的深度学习模型&#xff0c;将自然语言与三维内容生成紧密结合&#xff0c;开…

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;它可以与…

2024年五一数学建模竞赛赛题浅析-助攻快速选题

题目 复杂性 技术需求 数据处理需求 主要难点 综合评估 A题 高 优化算法、图论、启发式搜索 几何数据解析和路径计算 设计有效的路径优化算法来最小化空程&#xff0c;处理几何布局的复杂性 2 B题 非常高 网络流优化、线性/非线性规划 大规模网络数据处理和流量…

GPT每日面试题—csrf攻击的原理和解决方案

充分利用ChatGPT的优势&#xff0c;帮助我们快速准备前端面试。今日问题&#xff1a;csrf原理和解决方案? Q&#xff1a;如果在前端面试中&#xff0c;被问到csrf原理和解决方案&#xff0c;怎么回答比较好&#xff0c;全面具体的描述一下 A&#xff1a;在前端面试中&#xf…

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…

Apktool 反编译、修改、重打包学习使用及问题处理

反编译 $ apktool d app.apk -r --only-main-classes -o destDir d 表示反编译 app.apk 是目标apk文件路径-r 表示不反编译资源文件 --only-main-classes 表示不反编译某些资源文件目录下的dex文件&#xff0c;这些dex文件通常是被加固的dex.-o 反编译后代码存放目录 修改 …