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 即可!!! [ 命令模式 ] 切换至 [ 插…...
阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
PPT|230页| 制造集团企业供应链端到端的数字化解决方案:从需求到结算的全链路业务闭环构建
制造业采购供应链管理是企业运营的核心环节,供应链协同管理在供应链上下游企业之间建立紧密的合作关系,通过信息共享、资源整合、业务协同等方式,实现供应链的全面管理和优化,提高供应链的效率和透明度,降低供应链的成…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放
简介 前面两期文章我们介绍了I2S的读取和写入,一个是通过INMP441麦克风模块采集音频,一个是通过PCM5102A模块播放音频,那如果我们将两者结合起来,将麦克风采集到的音频通过PCM5102A播放,是不是就可以做一个扩音器了呢…...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
ffmpeg(四):滤镜命令
FFmpeg 的滤镜命令是用于音视频处理中的强大工具,可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下: ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜: ffmpeg…...
【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
