数据结构双向链表和循环链表
目录
- 一、循环链表
- 二、双向链表
- 三、循环双向链表
一、循环链表
循环链表就是首尾相接的的链表,就是尾节点的指针域指向头节点使整个链表形成一个循环,这就弥补了以前单链表无法在后面某个节点找到前面的节点,可以从任意一个节点找到目标节点,但是现在我们就不能像以前那样停止循环时的判断条件是否为NULL了,而是判断是否指向头指针


由于我们的操作经常是在链表的首位进行操作,所以我们引进尾指针的概念,这样以后就可以直接找到操作尾节点

下面是循环单链表的相关代码:
typedef struct
{int data;Lnode* next;
}*CirList,Lnode;//初始化一个循环单链表
bool init_list(CirList& l)
{l = new Lnode;//开辟空间作为头节点if (l == NULL)return false;l->next = l;//头指针的指针域指向自己return true;
}//判断循环单链表是否为空表
bool isEmpty(CirList& l)
{if (l->next == l)return true;return false;
}
二、双向链表
由于单链表无法逆向检索,循环链表逆向寻找元素时间复杂度也是O(n),所以这里提出双向链表的概念,就是给每个元素一个前驱指针,这样我们就可以直接逆向检索上一个元素了,而且时间复杂度为O(1);双向链表的空表里面两个指针装的都是空指针

#include<iostream>
using namespace std;
typedef struct Lnode
{int data;Lnode* next,*prior;
}*DoubList,Lnode;//初始化一个双向链表
bool init_list(DoubList& l)
{l = new Lnode;if (l == NULL)return false;l->next = NULL;l->prior = NULL;return true;
}//双向链表建立(前插法)
bool insert_list(DoubList& l)
{init_list(l);int x;while (cin >> x && x != 0){Lnode* p = new Lnode{x,l->next,l};if (p == NULL)return false;if (l->next)l->next->prior = p;l->next = p;}return true;
}//双链表建立(后插法)
bool insert_tail_list(DoubList& l)
{init_list(l);int x;Lnode* r =l;while (cin >> x && x != 0){Lnode* p = new Lnode{ x,NULL,r };if (p == NULL)return false;r->next = p;r = p;}return true;
}//按位插入:在i位插入元素e
bool insertElem(DoubList& l, int i, int e)
{if (i < 1)return false;int j=0;Lnode* r = l;while (j < i - 1 && r->next != NULL){r = r->next;j++;}if (j != i - 1)return false;Lnode* p = new Lnode{ e,r->next,r };if (r->next)r->next->prior = p;r->next = p;return true;
}//按值删除元素e
void deleteElem(DoubList&l,int e)
{if (!l->next)cout << "删除失败:链表为空" << endl;Lnode* r = l->next;while (r){if (r->data == e){r->prior->next = r->next;if (r->next)r->next->prior = r->prior;delete r;r = NULL;return;}r = r->next;}
}//打印双链表
void print(DoubList l)
{Lnode* p=l;while (p->next){p = p->next;cout << p->data << "\t";}cout << endl;
}int main()
{DoubList l;insert_list(l);print(l);deleteElem(l, 3);print(l);return 0;
}
三、循环双向链表
即使我们有了双向链表,但是当我们想要在尾节点找到头节点附近某个节点仍然不够快捷,所以就引进了循环双向链表的概念,不过判断条件这些就需要改变:判断结束条件从NULL变为链表名L
#include<iostream>
using namespace std;
typedef struct Lnode
{int data;Lnode* next,*prior;
}*DoubCirList,Lnode;//初始化一个循环双向链表
bool init_list(DoubCirList& l)
{l = new Lnode;if (l == NULL)return false;//指针域都指向自身l->next = l;l->prior = l;return true;
}//双向循环链表建立(前插法)
bool insert_list(DoubCirList& l)
{init_list(l);int x;while (cin >> x && x != 0){Lnode* p = new Lnode{x,l->next,l};if (p == NULL)return false;l->next->prior = p;l->next = p;}return true;
}//双链表建立(后插法)
bool insert_tail_list(DoubCirList& l)
{init_list(l);int x;Lnode* r =l;while (cin >> x && x != 0){Lnode* p = new Lnode{ x,l,r };if (p == NULL)return false;r->next = p;r = p;}return true;
}//按位插入:在i位插入元素e
bool insertElem(DoubCirList& l, int i, int e)
{if (i < 1)return false;int j=0;Lnode* r = l;while (j < i - 1 && r->next != l){r = r->next;j++;}if (j != i - 1)return false;Lnode* p = new Lnode{ e,r->next,r };r->next->prior = p;r->next = p;return true;
}//按值删除元素e
void deleteElem(DoubCirList&l,int e)
{if (l->next==l)cout << "删除失败:链表为空" << endl;Lnode* r = l->next;while (r!=l){if (r->data == e){r->next->prior = r->prior;r->prior->next = r->next;delete r;r = NULL;return;}r = r->next;}
}//打印双链表
void print(DoubCirList l)
{Lnode* p=l;while (p->next!=l){p = p->next;cout << p->data << "\t";}cout << endl;
}int main()
{DoubCirList l;insert_tail_list(l);print(l);return 0;
}
相关文章:
数据结构双向链表和循环链表
目录 一、循环链表二、双向链表三、循环双向链表 一、循环链表 循环链表就是首尾相接的的链表,就是尾节点的指针域指向头节点使整个链表形成一个循环,这就弥补了以前单链表无法在后面某个节点找到前面的节点,可以从任意一个节点找到目标节点…...
go基础面试题汇总第一弹
init函数是什么时候执行的? init的函数的作用是什么? 通常作为程序执行前包的初始化,例如mysql redis 等中间件的初始化 init函数的执行顺序是怎样的? 分不同情况来回答: 在同一个go文件里面如果有多个init方法,它们…...
Redis 实现分布式锁时需要考虑的问题
引言 分布式系统中的多个节点经常需要对共享资源进行并发访问,若没有有效的协调机制,可能会导致数据竞争、资源冲突等问题。分布式锁应运而生,它是一种保证在分布式环境中多个节点可以安全地访问共享资源的机制。而在Redis中,使用…...
百年极限论一直存在百年糊涂话:有正数小于所有正数
百年极限论一直存在百年糊涂话:有正数小于所有(任何、任意)正数。 “对于每个大于0的ε[ε>0],都有非0距离数小于ε”显然是病句:有正数小于每个(所有)正数ε。其中任意(任何&am…...
红日靶场1学习笔记
一、准备工作 1、靶场搭建 靶场地址 靶场描述 靶场拓扑图 其他相关靶场搭建详情见靶场地址相关说明 2、靶场相关主机信息 后续打靶场的过程中,如果不是短时间内完成,可能ip会有变化 主机ip密码角色win7192.168.122.131hongrisec2019!边界服务器win…...
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
文章目录 从零实现 list 容器:细粒度剖析与代码实现前言1. list 的核心数据结构1.1节点结构分析: 2. 迭代器设计与实现2.1 为什么 list 需要迭代器?2.2 实现一个简单的迭代器2.2.1 迭代器代码实现:2.2.2 解释: 2.3 测试…...
【C#生态园】打造现代化跨平台应用:深度解析.NET桌面应用工具
选择最适合你的.NET UI框架:全面解析六种热门选择 前言 在现代软件开发中,选择合适的桌面应用框架和UI库对于开发人员来说至关重要。本文将介绍几种流行的.NET桌面应用框架和UI库,包括Eto.Forms、Avalonia、ReactiveUI、MahApps.Metro、Mat…...
第二十一章 (动态内存管理)
1. 为什么要有动态内存分配 2. malloc和free 3. calloc和realloc 4. 常⻅的动态内存的错误 5. 动态内存经典笔试题分析 6. 总结C/C中程序内存区域划分 1.为什么要有动态内存管理 我们目前已经掌握的内存开辟方式有 int main() {int num 0; //开辟4个字节int arr[10] …...
机器学习框架总结
机器学习框架是用于构建、训练、评估和部署机器学习模型的工具和库的集合。它们简化了模型开发过程,并提供了预构建的功能、优化的计算性能和对深度学习、监督学习、无监督学习等技术的支持。下面是一些主要的机器学习框架的详细介绍: 1. TensorFlow 1…...
docker pull 超时的问题如何解决
docker不能使用,使用之前的阿里云镜像失败。。。 搜了各种解决方法,感谢B站UP主 <iframe src"//player.bilibili.com/player.html?isOutsidetrue&aid113173361331402&bvidBV1KstBeEEQR&cid25942297878&p1" scrolling"…...
【数学分析笔记】第4章第3节 导数四则运算和反函数求导法则(2)
4. 微分 4.3 导数四则运算与反函数求导法则 双曲正弦函数 sh x e x − e − x 2 \sh x\frac{e^x-e^{-x}}{2} shx2ex−e−x 双曲余弦函数 ch x e x e − x 2 \ch x\frac{e^xe^{-x}}{2} chx2exe−x ch 2 x − sh 2 x 1 \ch^2 x-\sh^2 x1 ch2x−sh2x1 ( e…...
【2024】基于mysqldump的数据备份与恢复
基于mysqldump备份与恢复 mysqldump是一个用于备份 MySQL 数据库的实用工具。 它可以将数据库的结构(如数据库、表、视图、存储过程等的定义)和数据(表中的记录)导出为文本文件,这些文本文件可以包含 SQL 语句&#…...
家用无线路由器配置
一.首先进行线路连接。如下图:"光猫LAN口"—网线—"路由器WAN口"。 注意:家用光纤宽带一般选择使用200兆宽带到1000兆,如果网速不达标请查看路由器是否是千兆路由器。千兆路由器通常是双频的,支持两个信号一个…...
模拟算法(4)_外观数列
个人主页:C忠实粉丝 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C忠实粉丝 原创 模拟算法(4)_外观数列 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记,欢迎大家在评论区交流讨论💌 目录 1. 题目链…...
vsomeip用到的socket
概述: vsomeip用到的socket的代码全部都在implementation\endpoints目录下面,主要分布在下面六个endpoint类中: local_client_endpoint_impl // 本地客户端socket(UDS Socket或者127.0.0.1的socket)local_server…...
MFC有三个选项:MFC ActiveX控件、MFC应用程序、MFC DLL,如何选择?
深耕AI:互联网行业 算法研发工程师 目录 MFC ActiveX 控件 控件的类型 标准控件 自定义控件 ActiveX控件 MFC ActiveX控件 标准/自定义控件 MFC ActiveX控件分类 3种MFC如何选择? MFC ActiveX控件 MFC 应用程序 MFC DLL 总结 举例说明…...
边缘概率 | 条件概率
关于什么是边缘概率分布和条件概率分布,在理论上,我自己也还没有理解,那么现在就根据我学习到的理解方式来记录一下,有错误指出,请大家指正!!! 例如,一个箱子里有十个乒乓…...
深入浅出:现代JavaScript开发者必知必会的Web性能优化技巧
亲爱的读者们,欢迎来到本期博客。今天,我们将深入探讨JavaScript开发者在日常工作中如何提升Web性能。在快节奏的Web开发世界中,性能优化至关重要。本文将分享一些实用技巧,帮助你构建快速、高效的Web应用。 1. 使用CDN加速资源加…...
【S32K3 RTD LLD篇5】K344 ADC SW+HW trigger
【S32K3 RTD LLD篇5】K344 ADC SWHW trigger 一,文档简介二,ADC SW HW 触发2.1 软硬件平台2.2 SWADC 软件触发2.3 SWBCTUADC 软件BCTU触发2.4 PITTRIGMUXADC 硬件PIT TRIGUMX触发2.5 EMIOSBCTUHWADC硬件EMIOS BCTU触发2.6 EMIOSBCTUHW LISTADC硬件EMIOS …...
TransFormer 视频笔记
TransFormer BasicsAttention单头注意力 single head attentionQ: query 查寻矩阵 128*12288K key matrix 128*12288SoftMax 归一 Value matrix 12288*12288 MLP Bas…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...
GraphQL 实战篇:Apollo Client 配置与缓存
GraphQL 实战篇:Apollo Client 配置与缓存 上一篇:GraphQL 入门篇:基础查询语法 依旧和上一篇的笔记一样,主实操,没啥过多的细节讲解,代码具体在: https://github.com/GoldenaArcher/graphql…...
