C++11 数据结构3 线性表的循环链式存储,实现,测试
上一节课,我们学了线性表 单向存储结构(也就是单链表),这个是企业常用的技术,且是后面各种的基本,一定要牢牢掌握,如果没有掌握,下面的课程会云里雾里。
一 ,循环链表
1、什么是循环链表
— 概念上:
1、任何数据元素都有一个前驱和一个后继
2、所有的数据元素的关系构成一个逻辑的环
— 实现上:
1、循环链表是一种特殊的单链表
2、尾结点的指针域保存了首结点的地址
2、循环链表的逻辑构成
二 循环链表的插入示意图
头插法第一次插入
头插法非第一次插入
删除非第一个元素
删除第一个元素
三 代码实现
.h实现
#ifndef _003CIRCLELIST_H_
#define _003CIRCLELIST_H_typedef void CircleList; //要返回给上层的list 的首地址为 void *,为了阅读起名为CircleListtypedef struct _tag_CircleListNode //list 中的节点
{struct _tag_CircleListNode* next;
}CircleListNode;//创建循环链表
CircleList* CircleList_Create();//销毁循环链表
void CircleList_Destroy(CircleList* list);//清空循环列表
void CircleList_Clear(CircleList* list);//循环列表中目前存在的元素个数
int CircleList_Length(CircleList* list);//给循环列表中插入元素,node为要插入的元素的值,pos为位置
int CircleList_Insert(CircleList* list, CircleListNode* node, int pos);//从循环列表中的pos 位置获得具体的值
CircleListNode* CircleList_Get(CircleList* list, int pos);//从循环列表中删除pos位置的数据
CircleListNode* CircleList_Delete(CircleList* list, int pos);//从循环列表中删除 数据 为node 的点
CircleListNode* CircleList_DeleteNode(CircleList* list, CircleListNode* node);CircleListNode* CircleList_Reset(CircleList* list);CircleListNode* CircleList_Current(CircleList* list);CircleListNode* CircleList_Next(CircleList* list);#endif
底层实现
#include "003CircleList.h"
#include "stdio.h"
#include "stdlib.h"
#include <string.h>typedef struct _tag_CircleList{CircleListNode header;CircleListNode* slider; //多了一个游标int length;
} TCircleList;CircleList* CircleList_Create(){TCircleList* ret = (TCircleList*)malloc(sizeof(TCircleList));if (ret == NULL) {printf("CircleList_Create func malloc error\n");return ret;}memset(ret,0,sizeof(TCircleList));ret->length = 0;ret->header.next = NULL;ret->slider = NULL;return ret;
}void CircleList_Destroy(CircleList* list) // O(1)
{free(list);
}void CircleList_Clear(CircleList* list){TCircleList* sList = (TCircleList*)list;if (sList != NULL){sList->length = 0;sList->header.next = NULL;sList->slider = NULL;}
}int CircleList_Length(CircleList* list){TCircleList* sList = (TCircleList*)list;int ret = -1;if (sList != NULL){ret = sList->length;}return ret;
}int CircleList_Insert(CircleList* list, CircleListNode* node, int pos) // O(n)
{TCircleList* sList = (TCircleList*)list;int ret = (sList != NULL) && (pos >= 0) && (node != NULL);int i = 0;if (ret){CircleListNode* current = (CircleListNode*)sList;//current指向头部for (i = 0; (i < pos) && (current->next != NULL); i++){current = current->next;}//假设我们要插入的是pos =3,头结点不算,下来从0,1,2,3,4,5,6开始计算//循环完成后,current刚好是在 pos=2的位置,//要变成的是 2 node 3 ,也就是说node->next要是3node->next = current->next;//current的->next,现在也是2,指向新的节点nodecurrent->next = node;if (sList->length == 0){//如果是第一次插入将slider的指向nodesList->slider = node;}sList->length++;//如果是头插法,还需要做事情,让最后一个元素链接到这个新节点,if (current == (CircleListNode*)sList) {CircleListNode * last = CircleList_Get(list,sList->length-1);last->next = node;}//此处要理解,需结合图来看,后续会将 头插法,尾插法,中间插入法的三种图示画一下,方便理解}return ret;
}CircleListNode* CircleList_Get(CircleList* list, int pos) // O(n)
{TCircleList* sList = (TCircleList*)list;CircleListNode* ret = NULL;int i = 0;if ((sList != NULL) && (pos >= 0)){CircleListNode* current = (CircleListNode*)sList;for (i = 0; i < pos; i++){current = current->next;}ret = current->next;}return ret;
}CircleListNode* CircleList_Delete(CircleList* list, int pos) // O(n)
{TCircleList* sList = (TCircleList*)list;CircleListNode* ret = NULL;int i = 0;if ((sList != NULL) && (pos >= 0)){CircleListNode* current = (CircleListNode*)sList;CircleListNode* first = sList->header.next;CircleListNode* last = (CircleListNode*)CircleList_Get(sList, sList->length - 1);for (i = 0; i < pos; i++){current = current->next;}ret = current->next;current->next = ret->next;sList->length--;//如果删除的第一个结点。要额外处理if (first == ret){//让头结点的next要重新指向,指向的内容是保存在 被删除的节点的next中的。sList->header.next = ret->next;//让最后一个节点的next也要重新指向,指向的内容是保存在 被删除的节点的next中的。last->next = ret->next;}//如果删除的元素刚好是 游标指向的元素,则将游标往下移动if (sList->slider == ret){sList->slider = ret->next;}//如果list只有一个元素,删除后,就没有元素了,那么就需要将if (sList->length == 0){sList->header.next = NULL;sList->slider = NULL;}}return ret;
}CircleListNode* CircleList_DeleteNode(CircleList* list, CircleListNode* node) // O(n)
{TCircleList* sList = (TCircleList*)list;CircleListNode* ret = NULL;int i = 0;if (sList != NULL){CircleListNode* current = (CircleListNode*)sList;for (i = 0; i < sList->length; i++){if (current->next == node){ret = current->next;break;}current = current->next;}if (ret != NULL){CircleList_Delete(sList, i);}}return ret;
}CircleListNode* CircleList_Reset(CircleList* list) // O(1)
{TCircleList* sList = (TCircleList*)list;CircleListNode* ret = NULL;if (sList != NULL){sList->slider = sList->header.next;ret = sList->slider;}return ret;
}CircleListNode* CircleList_Current(CircleList* list) // O(1)
{TCircleList* sList = (TCircleList*)list;CircleListNode* ret = NULL;if (sList != NULL){ret = sList->slider;}return ret;
}CircleListNode* CircleList_Next(CircleList* list) // O(1)
{TCircleList* sList = (TCircleList*)list;CircleListNode* ret = NULL;if ((sList != NULL) && (sList->slider != NULL)){ret = sList->slider;sList->slider = ret->next;}return ret;
}
测试代码
#include "iostream"
#include <stdio.h>
#include <stdlib.h>extern "C" {
#include "003CircleList.h"
}using namespace std;struct Value
{CircleListNode header;int v;
};int main(int argc, char *argv[]){int i = 0;CircleList* list = CircleList_Create();struct Value v1;struct Value v2;struct Value v3;struct Value v4;struct Value v5;struct Value v6;struct Value v7;struct Value v8;v1.v = 1;v2.v = 2;v3.v = 3;v4.v = 4;v5.v = 5;v6.v = 6;v7.v = 7;v8.v = 8;CircleList_Insert(list, (CircleListNode*)&v1, CircleList_Length(list));CircleList_Insert(list, (CircleListNode*)&v2, CircleList_Length(list));CircleList_Insert(list, (CircleListNode*)&v3, CircleList_Length(list));CircleList_Insert(list, (CircleListNode*)&v4, CircleList_Length(list));for (i = 0; i < CircleList_Length(list); i++){struct Value* pv = (struct Value*)CircleList_Get(list, i);printf("%d\n", pv->v);}//注意这里,这时候list除了头结点外,只有4个元素,1,2,3,4,对应0,1,2,3//代码中插入的pos =5,相当于在1和2中间插入一个5.CircleList_Insert(list, (CircleListNode*)&v5, 5);//因此如下的循环后,打印出来的是 1,5,2,3,4for (i = 0; i < CircleList_Length(list); i++){struct Value* pv = (struct Value*)CircleList_Get(list, i);printf("%d\n", pv->v);}CircleList_Delete(list, 0);//删除第一个元素,将1删除了//再次打印是 5 2 3 4 5 2 3 4for (i = 0; i < 2 * CircleList_Length(list); i++){struct Value* pv = (struct Value*)CircleList_Get(list, i);printf("%d\n", pv->v);}printf("\n");while (CircleList_Length(list) > 0){struct Value* pv = (struct Value*)CircleList_Delete(list, 0);printf("%d\n", pv->v);}printf("aaaaaa\n");CircleList_Insert(list, (CircleListNode*)&v1, 0);CircleList_Insert(list, (CircleListNode*)&v2, 0);CircleList_Insert(list, (CircleListNode*)&v3, 0);CircleList_Insert(list, (CircleListNode*)&v4, 0);CircleList_Insert(list, (CircleListNode*)&v5, 0);CircleList_Insert(list, (CircleListNode*)&v6, 0);CircleList_Insert(list, (CircleListNode*)&v7, 0);CircleList_Insert(list, (CircleListNode*)&v8, 0);//注意,这里是用的头插法,因此是8,7,6,5,4,3,2,1,但是第一个插入的是1,因此游标指向1,又因为是循环的,因此下一个是8,结果是1,8,7,6,5,4,3,2for (i = 0; i < CircleList_Length(list); i++){struct Value* pv = (struct Value*)CircleList_Next(list);printf("%d\n", pv->v);}printf("bbbbbbbbbb\n");//游标reset 是指向的第一个元素CircleList_Reset(list);//1,2,3 将3剔除队列的游戏,游标reset后,指向的是8,因此123,将3剔除队列的有些结果为 6,3,8,4,7,1,5,2while (CircleList_Length(list) > 0){struct Value* pv = NULL;for (i = 1; i < 3; i++){CircleList_Next(list);}printf("ccc\n");//游标reset之后,指向数字8,往后移动了2次,就是指向6pv = (struct Value*)CircleList_Current(list);printf("%d\n", pv->v);CircleList_DeleteNode(list, (CircleListNode*)pv);}CircleList_Destroy(list);return 0;}
相关文章:

C++11 数据结构3 线性表的循环链式存储,实现,测试
上一节课,我们学了线性表 单向存储结构(也就是单链表),这个是企业常用的技术,且是后面各种的基本,一定要牢牢掌握,如果没有掌握,下面的课程会云里雾里。 一 ,循环链表 1…...

初识DOM
目录 前言: 1.初识DOM: 1.1DOM树: 1.2节点(Node): 1.2.1元素节点: 1.2.2属性节点: 1.2.3文本节点: 1.3Document对象: 2.操作网页元素: 2.1找出元素: 2.1.1document.getElementById(id)࿱…...

计算机视觉实验五——图像分割
计算机视觉实验五——图像分割 一、实验目标二、实验内容1.了解图割操作,实现用户交互式分割,通过在一幅图像上为前景和背景提供一些标记或利用边界框选择一个包含前景的区域,实现分割①图片准备②代码③运行结果④代码说明 2.采用聚类法实现…...

移动Web学习06-移动端适配Less预处理器项目案例
项目目标:实现在不同宽度设备中等比缩放的网页效果 Less代码 import ./base; import ./normalize;// 变量: 存储37.5 rootSize: 37.5rem; *{margin: 0;padding: 0; } body {background-color: #F0F0F0; }// 主体内容 .main {// padding-bottom: (50 / 37.5rem);pa…...

LangChain-25 ReAct 让大模型自己思考和决策下一步 AutoGPT实现途径、AGI重要里程碑
背景介绍 大模型ReAct(Reasoning and Acting)是一种新兴的技术框架,旨在通过逻辑推理和行动序列的构建,使大型语言模型(LLM)能够达成特定的目标。这一框架的核心思想是赋予机器模型类似人类的推理和行动能…...
24/04/15总结
多线程: 线程 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位 并发:在同一时刻,有多个指令在单个cpu上交替执行 并行:在同一时刻,有多个指令在多个cpu上同时执行 多线程的实现方式 1.继承…...
vue3、vue2中nextTick源码解析
nexttick是啥 nextTick是Vue提供的一个全局API,由于Vue的异步更新策略导致我们对数据的修改不会更新,如果此时想要获取更新后的Dom,就需要使用这个方法. vue的异步更新策略意思是如果数据变化,vue不会立刻更新dom,而是开启一个队列,把组件更…...

【氮化镓】GaN HEMTs结温和热阻测试方法
文章《Temperature rise detection in GaN high-electron-mobility transistors via gate-drain Schottky junction forward-conduction voltages》,由Xiujuan Huang, Chunsheng Guo, Qian Wen, Shiwei Feng, 和 Yamin Zhang撰写,发表在《Microelectroni…...

c++11 标准模板(STL)本地化库 - 平面类别(std::codecvt) - 在字符编码间转换,包括 UTF-8、UTF-16、UTF-32 (四)
本地化库 本地环境设施包含字符分类和字符串校对、数值、货币及日期/时间格式化和分析,以及消息取得的国际化支持。本地环境设置控制流 I/O 、正则表达式库和 C 标准库的其他组件的行为。 平面类别 在字符编码间转换,包括 UTF-8、UTF-16、UTF-32 std::…...

【状态压缩 容斥原理 组合数学】100267. 单面值组合的第 K 小金额
本文涉及知识点 状态压缩 容斥原理 组合数学 二分查找算法合集 LeetCode100267. 单面值组合的第 K 小金额 给你一个整数数组 coins 表示不同面额的硬币,另给你一个整数 k 。 你有无限量的每种面额的硬币。但是,你 不能 组合使用不同面额的硬币。 返回…...

.net框架和c#程序设计第三次测试
目录 一、测试要求 二、实现效果 三、实现代码 一、测试要求 二、实现效果 数据库中的内容: 使用数据库中的账号登录: 若不是数据库中的内容: 三、实现代码 login.aspx文件: <% Page Language"C#" AutoEventW…...

架构师系列-搜索引擎ElasticSearch(五)- 索引设计
索引创建后,要非常谨慎,创建不好后面会出现各种问题。 索引设计的重要性 索引创建后,索引分片只能通过_split和_shrink 接口对其进行成倍的增加和缩减。 ES的数据是通过_routing分配到各个分片上的,所以本质上不推荐区改变索引的…...
kafka ----修改log4j、jmx、jvm参数等
1、修改log4j 日志路径 在kafka-run-class.sh文件中修改如下配置,将 LOG_DIR变量指定为自己想要存储的路径 # Log directory to use if [ "x$LOG_DIR" "x" ]; thenLOG_DIR"$base_dir/logs" fi2、修改jmx参数 在kafka-run-class.s…...

Python 全栈 Web 应用模板:成熟架构,急速开发 | 开源日报 No.223
tiangolo/full-stack-fastapi-template Stars: 15.6k License: MIT full-stack-fastapi-template 是一个现代化的全栈 Web 应用模板。 使用 FastAPI 构建 Python 后端 API。使用 SQLModel 进行 Python SQL 数据库交互(ORM)。Pydantic 用于数据验证和设…...

STM32之DHT11温湿度传感器
目录 一 DHT11温湿度传感器简介 1.1 传感器特点 1.2 传感器特性 1.3 传感器引脚说明 二 测量原理及方法 2.1 典型应用电路 2.2 单线制串行简介 2.2.1 串行接口 (单线双向) 2.2.2 数据示例 2.3 通信时序 三 单片机简介 3.1 STM32F103C8T6最小系统板 四 接线说明 …...
paddle ocr
paddle安装教程,git clone xxxgit https://blog.csdn.net/Castlehe/article/details/117356343 只有paddle 1.x 的教程:https://github.com/PaddlePaddle/PaddleOCR/blob/static/doc/doc_en/quickstart_en.md 报错是因为安装的是paddle 2.x而教程只给了…...

Xcode 15.0 新 #Preview 预览让 SwiftUI 界面调试更加悠然自得
概览 从 Xcode 15 开始,苹果推出了新的 #Preview 宏预览机制,它无论从语法还是灵活性上都远远超过之前的预览方式。#Preview 不但可以实时预览 SwiftUI 视图,而且对 UIKit 的界面预览也是信手拈来。 想学习新 #Preview 预览的一些超实用调试…...

【VS2019】x64 Native Tools Command Prompt for Vs 2019使用conda命令进入环境
【VS2019】x64 Native Tools Command Prompt for Vs 2019使用conda命令进入环境 安装完VS2019后,打开终端x64 Native Tools Command Prompt for Vs 2019,直接运行conda会出现‘conda’ 不是内部或外部命令,也不是可运行的程序 原因分析&am…...

网络篇09 | 运输层 udp
网络篇09 | 运输层 udp 01 简介UDP 是面向报文的 02 报文协议 01 简介 UDP 只在 IP 的数据报服务之上增加了一些功能:复用和分用、差错检测 UDP 的主要特点:无连接。发送数据之前不需要建立连接。 使用尽最大努力交付。即不保证可靠交付。 面向报文。…...

vim相关指令
vim的各种模式及其转换关系图 vim 默认处于命令模式!!! 模式之间转换的指令 除【命令模式】之外,其它模式要切换到【命令模式】,只需要无脑 ESC 即可!!! [ 命令模式 ] 切换至 [ 插…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
质量体系的重要
质量体系是为确保产品、服务或过程质量满足规定要求,由相互关联的要素构成的有机整体。其核心内容可归纳为以下五个方面: 🏛️ 一、组织架构与职责 质量体系明确组织内各部门、岗位的职责与权限,形成层级清晰的管理网络…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
Java 加密常用的各种算法及其选择
在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。 一、对称加密算法…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...

技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...