当前位置: 首页 > news >正文

第 2 章 线性表 ( 双链循环线性表(链式存储结构)实现)

1. 背景说明

 

 

2. 示例代码

1) status.h

/* DataStructure 预定义常量和类型头文件 */#ifndef STATUS_H
#define STATUS_H#define CHECK_NULL(pointer) if (!(pointer)) { \printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_NULL_PTR); \return NULL; \
}#define CHECK_RET(ret) if (ret != RET_OK) { \printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ret); \return ret; \
}#define CHECK_VALUE(value, ERR_CODE) if (value) { \printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_CODE); \return ERR_CODE; \
}#define CHECK_FALSE(value, ERR_CODE) if (!(value)) { \printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_CODE); \return FALSE; \
} /* 函数结果状态码 */
#define TRUE 					1			/* 返回值为真 */
#define FALSE 					0			/* 返回值为假 */
#define RET_OK 					0			/* 返回值正确 */
#define INFEASIABLE    		   	2			/* 返回值未知 */
#define ERR_MEMORY     		   	3			/* 访问内存错 */
#define ERR_NULL_PTR   			4			/* 空指针错误 */
#define ERR_MEMORY_ALLOCATE		5			/* 内存分配错 */
#define ERR_NULL_STACK			6			/* 栈元素为空 */
#define ERR_PARA				7			/* 函数参数错 */
#define ERR_OPEN_FILE			8			/* 打开文件错 */
#define ERR_NULL_QUEUE			9			/* 队列为空错 */
#define ERR_FULL_QUEUE			10			/* 队列为满错 */
#define ERR_NOT_FOUND			11			/* 表项不存在 */
typedef int Status;							/* Status 是函数的类型,其值是函数结果状态代码,如 RET_OK 等 */
typedef int Bollean;						/* Boolean 是布尔类型,其值是 TRUE 或 FALSE */#endif // !STATUS_H

2) cycleDoubleLinkList.h

/* 双链循环线性表(链式存储结构)头文件实现 */#ifndef CYCLEDOUBLELINKLIST_H
#define CYCLEDOUBLELINKLIST_H#include "status.h"typedef int ElemType;typedef struct DuLNode {ElemType data;struct DuLNode *prior, *next;
} DuLNode, *DuLinkList;/* 产生空的双向循环链表 L */
Status InitList(DuLinkList *L);/* 操作结果:销毁双向循环链表 L */
Status DestroyList(DuLinkList *L);/* 初始条件:L 已存在操作结果:将 L 重置为空表 */
Status ClearList(DuLinkList L);/* 初始条件:线性表 L 已存在操作结果:若 L 为空表,则返回 TRUE,否则返回 FALSE */
Bollean ListEmpty(DuLinkList L);/* 初始条件:L 已存在操作结果:返回 L 中数据元素个数 */
int ListLength(DuLinkList L);/* 当第 i 个元素存在时,其值赋给 e 并返回 OK,否则返回 ERROR */
Status GetElem(DuLinkList L, int i, ElemType *e);/* 初始条件:L 已存在,compare() 是数据元素判定函数操作结果:返回 L 中第 1 个与 e 满足关系 compare() 的数据元素的位序若这样的数据元素不存在,则返回值为 0 */
int LocateElem(DuLinkList L, ElemType e, Status(*compare)(ElemType, ElemType));/* 操作结果:若 curr_e 是 L 的数据元素,且不是第一个,则用 pre_e 返回它的前驱否则操作失败,pre_e 无定义 */
Status PriorElem(DuLinkList L, ElemType curr_e, ElemType *pre_e);/* 操作结果:若 curr_e 是 L 的数据元素,且不是最后一个,则用 next_e 返回它的后继否则操作失败,next_e 无定义 */
Status NextElem(DuLinkList L, ElemType curr_e, ElemType *next_e);/* 在双向链表 L 中返回第 i 个元素的位置指针 */
DuLinkList GetElemP(DuLinkList L, int i);/* 算法 2.18,在带头结点的双链循环线性表 L 中第 i 个位置之前插入元素 e,i 的合法值为 1≤ i ≤ 表长 + 1 */
Status ListInsert(DuLinkList L, int i, ElemType e);/* 算法 2.19,删除带头结点的双链循环线性表 L 的第 i 个元素,i 的合法值为 1 ≤ i ≤ 表长 */
Status ListDelete(DuLinkList L, int i, ElemType *e);/* 由双链循环线性表 L 的头结点出发,正序对每个数据元素调用函数 visit() */
void ListTraverse(DuLinkList L, void(*visit)(ElemType));/* 由双链循环线性表 L 的头结点出发,逆序对每个数据元素调用函数 visit() */
void ListTraverseBack(DuLinkList L, void(*visit)(ElemType));#endif // !CYCLEDOUBLELINKLIST_H

3) cycleDoubleLinkList.c

/* 双链循环线性表(链式存储结构)源文件实现 */#include "cycleDoubleLinkList.h"
#include <stdlib.h>
#include <stdio.h>static DuLinkList MakeNewDuLNode(ElemType e)
{DuLinkList newDuLNode = (DuLinkList)malloc(sizeof(DuLNode));CHECK_NULL(newDuLNode)newDuLNode->data = e;newDuLNode->prior = NULL;newDuLNode->next = NULL;return newDuLNode;
}/* 产生空的双向循环链表 L */
Status InitList(DuLinkList *L)
{*L = (DuLinkList)malloc(sizeof(DuLNode));CHECK_VALUE(!(*L), ERR_MEMORY_ALLOCATE)(*L)->next = (*L)->prior = *L;return RET_OK;
}/* 操作结果:销毁双向循环链表 L */
Status DestroyList(DuLinkList *L)
{DuLinkList p = (*L)->next;DuLinkList q;while (p != *L) {q = p->next;free(p);p = q;}free(*L);*L = NULL;return RET_OK;
}/* 初始条件:L 已存在操作结果:将 L 重置为空表 */
Status ClearList(DuLinkList L)
{DuLinkList p = L->next;DuLinkList q;while (p != L) {q = p->next;free(p);p = q;}L->next = L->prior = L;return RET_OK;
}/* 初始条件:线性表 L 已存在操作结果:若 L 为空表,则返回 TRUE,否则返回 FALSE */
Bollean ListEmpty(DuLinkList L)
{return ((L->next == L) && (L->prior == L)) ? TRUE : FALSE;
}/* 初始条件:L 已存在操作结果:返回 L 中数据元素个数 */
int ListLength(DuLinkList L)
{DuLinkList p = L->next;int length = 0;while (p != L) {++length;p = p->next;}return length;
}/* 当第 i 个元素存在时,其值赋给 e 并返回 OK,否则返回 ERROR */
Status GetElem(DuLinkList L, int i, ElemType *e)
{DuLinkList p = L->next;int count = 0;while ((p != L) && (count < i - 1)) {++count;p = p->next;}CHECK_VALUE((p == L) || count > i - 1, ERR_PARA)*e = p->data;return RET_OK;
}/* 初始条件:L 已存在,compare() 是数据元素判定函数操作结果:返回 L 中第 1 个与 e 满足关系 compare() 的数据元素的位序若这样的数据元素不存在,则返回值为 0 */
int LocateElem(DuLinkList L, ElemType e, Status(*compare)(ElemType, ElemType))
{DuLinkList p = L->next;int count = 0;while (p != L) {++count;if (compare(p->data, e)) {return count;}p = p->next;}return 0;
}/* 操作结果:若 curr_e 是 L 的数据元素,且不是第一个,则用 pre_e 返回它的前驱否则操作失败,pre_e 无定义 */
Status PriorElem(DuLinkList L, ElemType curr_e, ElemType *pre_e)
{DuLinkList p = L->next->next;while (p != L) {if (p->data == curr_e) {*pre_e = p->prior->data;return TRUE;}p = p->next;}return FALSE;
}/* 操作结果:若 curr_e 是 L 的数据元素,且不是最后一个,则用 next_e 返回它的后继否则操作失败,next_e 无定义 */
Status NextElem(DuLinkList L, ElemType curr_e, ElemType *next_e)
{DuLinkList p = L->next->next;while (p != L) {if (p->prior->data == curr_e) {*next_e = p->data;return TRUE;}p = p->next;}return FALSE;
}/* 在双向链表 L 中返回第 i 个元素的位置指针 */
DuLinkList GetElemP(DuLinkList L, int i)
{DuLinkList p = L;for (int j = 0; j < i; ++j) {p = p->next;}return p;
}/* 在带头结点的双链循环线性表 L 中第 i 个位置之前插入元素 e,i 的合法值为 1≤ i ≤ 表长 + 1 */
Status ListInsert(DuLinkList L, int i, ElemType e)
{CHECK_VALUE((i < 1 || i > ListLength(L) + 1), ERR_PARA)DuLinkList p = GetElemP(L, i - 1);CHECK_VALUE(!p, ERR_NOT_FOUND)DuLinkList newDuLNode = MakeNewDuLNode(e);CHECK_VALUE(!newDuLNode, ERR_MEMORY_ALLOCATE)newDuLNode->prior = p;newDuLNode->next = p->next;p->next->prior = newDuLNode;p->next = newDuLNode;return RET_OK;
}/* 删除带头结点的双链循环线性表 L 的第 i 个元素,i 的合法值为 1 ≤ i ≤ 表长 */
Status ListDelete(DuLinkList L, int i, ElemType *e)
{CHECK_VALUE((i < 1 || i > ListLength(L)), ERR_PARA)DuLinkList p = GetElemP(L, i);CHECK_VALUE(!p, ERR_NOT_FOUND)*e = p->data;p->prior->next = p->next;p->next->prior = p->prior;free(p);return RET_OK;
}/* 由双链循环线性表 L 的头结点出发,正序对每个数据元素调用函数 visit() */
void ListTraverse(DuLinkList L, void(*visit)(ElemType))
{DuLinkList p = L->next;while (p != L) {visit(p->data);p = p->next;}
}/* 由双链循环线性表 L 的头结点出发,逆序对每个数据元素调用函数 visit() */
void ListTraverseBack(DuLinkList L, void(*visit)(ElemType))
{DuLinkList p = L->prior;while (p != L) {visit(p->data);p = p->prior;}
}

4) main.c

/* 入口程序源文件 */#include "cycleDoubleLinkList.h"
#include <stdio.h>Status Compare(ElemType e1, ElemType e2);void Visit(ElemType e);int main(void)
{DuLinkList L;InitList(&L);for (int i = 0; i < 5; ++i) {ListInsert(L, i + 1, i + 1);}printf("Output Link List for sequence: ");ListTraverse(L, Visit);putchar('\n');printf("Output Link List for adverse: ");ListTraverseBack(L, Visit);putchar('\n');ElemType e;ListDelete(L, 2, &e);printf("After delete %d, Link List is: ", e);ListTraverse(L, Visit);putchar('\n');printf("The num of L is %d\n", ListLength(L));printf("List is %s\n", (ListEmpty(L) == TRUE) ? "empty" : "not empty");ClearList(L);printf("After clear L, List is %s\n", (ListEmpty(L) == TRUE) ? "empty" : "not empty");for (int i = 0; i < 5; ++i) {ListInsert(L, i + 1, i + 1);}ListTraverse(L, Visit);putchar('\n');Status ret = GetElem(L, 3, &e);if (ret == RET_OK) {printf("The %dth element of L is %d\n", 3, e);} else {printf("%dth element is not exist.\n", 3);}ret = LocateElem(L, 4, Compare);if (ret) {printf("The element of %d is %dth\n", 4, ret);} else {printf("Element %d is not exist in L\n", 4);}ret = PriorElem(L, 4, &e);if (ret == TRUE) {printf("The prior element of %d is %d\n", 4, e);} else {printf("Element %d do not have prior element\n", 4);}ret = NextElem(L, 4, &e);if (ret == TRUE) {printf("The next element of %d is %d\n", 4, e);} else {printf("Element %d do not have next element\n", 4);}DestroyList(&L);return 0;
}Status Compare(ElemType e1, ElemType e2)
{return (e1 == e2) ? TRUE : FALSE;
}void Visit(ElemType e)
{printf("%d ", e);
}

3. 输出示例

相关文章:

第 2 章 线性表 ( 双链循环线性表(链式存储结构)实现)

1. 背景说明 2. 示例代码 1) status.h /* DataStructure 预定义常量和类型头文件 */#ifndef STATUS_H #define STATUS_H#define CHECK_NULL(pointer) if (!(pointer)) { \printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_NULL_PTR…...

redis在日常开发工作中的常见用法

redis是一款内存型数据库&#xff0c;在开发工作中经常用到&#xff0c;功能强大&#xff1b; 特别开一篇文章用来记录一下它的常见用法&#xff0c;算是一种总结&#xff1b; 它最主要的特点就是高可用的&#xff0c;速度快&#xff0c;分布式&#xff1b;有人说速度快&…...

小程序实现下拉刷新

小程序实现下拉刷新可以通过使用组件scroll-view和事件onPullDownRefresh来实现。 scroll-view组件的使用 在需要下拉刷新的页面的wxml文件中&#xff0c;通过scroll-view组件包裹需要滚动的内容&#xff0c;设置scroll-y属性为true&#xff0c;表示允许竖向滚动。示例代码如…...

Day 36 贪心算法 part05 : 435. 无重叠区间 763.划分字母区间 56. 合并区间

56. 合并区间 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 示例 1&#xff1a; 输入&#xff1a;inte…...

使用Python将网页数据保存到NoSQL数据库的方法和示例

随着大数据和人工智能技术的快速发展&#xff0c;对于大规模数据的处理需求日益增多。NoSQL数据库作为一种新兴的数据存储解决方案&#xff0c;具有高可扩展性、高性能和灵活性数据模型等优势&#xff0c;已经在许多行业得到广泛应用。传统的关系型数据库在处理海量数据时可能会…...

两个路由器如何连接设置的方法攻略

一、前言 随着智能家居时代来临&#xff0c;家里的网络部署需求开始复杂起来。往往一个路由器已经不能满足需求或者不利于拓展。两个路由器连接最常见的情况是家中已有一个路由器&#xff0c;并且已经通过这个路由器来正常上网。现在是因某些原因想在不改变已经在用的路由器的设…...

分类任务评价指标

分类任务评价指标 分类任务中&#xff0c;有以下几个常用指标&#xff1a; 混淆矩阵准确率&#xff08;Accuracy&#xff09;精确率&#xff08;查准率&#xff0c;Precision&#xff09;召回率&#xff08;查全率&#xff0c;Recall&#xff09;F-scorePR曲线ROC曲线 1. 混…...

c++静态成员

目录 静态成员 静态成员变量 静态成员函数 const 静态成员属性 静态成员实现单例模式 静态成员 在类定义中&#xff0c;它的成员&#xff08;包括成员变量和成员函数&#xff09;&#xff0c;这些成员可以用关键字 static 声明为静态的&#xff0c;称为静态成员。 不管这…...

go-zero直连与etcd服务注册中心

go-zero中直连方式 在使用grpc是最重要的就是pb文件了&#xff0c;生成的pb文件&#xff0c;通过pb文件可以生成grpc的客户端和服务端&#xff0c;那么客户端和服务端就可以直连了&#xff0c;再次基础上可以引入etcd实现服务注册。 所有的代码都需要开发者编写&#xff0c;包…...

Kotlin File writeText appendText appendBytes readBytes readText

Kotlin File writeText appendText appendBytes readBytes readText import java.io.Filefun main(args: Array<String>) {val filePath "./myfile.txt"val file File(filePath)file.writeText("hello,") //如果原有文件有内容&#xff0c;将完全覆…...

常见缺少msvcp140.dll问题及解决方法,分享多种方法帮你解决

在日常使用电脑的过程中&#xff0c;我们可能会遇到各种问题&#xff0c;比如电脑提示msvcp140.dll文件丢失。这个问题通常是由于某些程序或游戏需要这个dll文件来正常运行&#xff0c;但是由于某种原因&#xff0c;这个文件被误删或者损坏了。那么&#xff0c;如何解决这个问题…...

【K210+ESP8266图传上位机开发】TCP server + JPEG图像解析上位机开发

本文章主要记录基于 【K210-ESP8266】 图传和显示的过程&#xff0c;上位机开发过程&#xff0c;系统架构和下位机开发请参考文章&#xff1a; 【K210-ESP8266】开发板上传图像数据到服务器并实时显示 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是喜欢记录零碎知…...

Linux查看当前文件夹的大小

在Linux中&#xff0c;可以使用du&#xff08;disk usage&#xff09;命令来查看当前文件夹的大小。以下是一些使用du的方法&#xff1a; 查看当前文件夹的大小&#xff1a; 为了查看当前文件夹的总大小&#xff0c;可以在文件夹中运行&#xff1a; du -sh .这里&#xff1a; -…...

YOLO目标检测——密集人群人头数据集+已标注yolo格式标签下载分享

实际项目应用&#xff1a;城市安防、交通管理、社会研究、商业应用、等多个领域数据集说明&#xff1a;YOLO密集人群人头目标检测数据集&#xff0c;真实场景的高质量图片数据&#xff0c;数据场景丰富&#xff0c;图片格式为jpg&#xff0c;共4300张图片。标注说明&#xff1a…...

论文精读 —— Gradient Surgery for Multi-Task Learning

文章目录 Multi-task Learning和 PCGrad 方法简介论文信息论文核心图摘要翻译引言翻译2 使用PCGrad进行多任务学习2.1 基本概念&#xff1a;问题和符号表示2.2 三重悲剧&#xff1a;冲突的梯度&#xff0c;主导的梯度&#xff0c;高曲率2.3 PCGrad&#xff1a;解决梯度冲突2.4 …...

【VS Code插件开发】常见自定义命令(七)

&#x1f431; 个人主页&#xff1a;不叫猫先生&#xff0c;公众号&#xff1a;前端舵手 &#x1f64b;‍♂️ 作者简介&#xff1a;前端领域优质作者、阿里云专家博主&#xff0c;共同学习共同进步&#xff0c;一起加油呀&#xff01; &#x1f4e2; 资料领取&#xff1a;前端…...

Spring Cloud服务发现与注册的原理与实现

Spring Cloud服务发现与注册的原理与实现 一、简介1 服务发现的定义2 服务发现的意义 二、Spring Cloud服务注册与发现的实现1 Spring Cloud服务注册1.1 服务注册的基本框架1.2 服务注册的实现方式 2 Spring Cloud服务发现2.1 服务发现的基本框架2.2 服务发现的实现方式 三、Sp…...

FFmpeg入门之简单介绍

FFmpeg是什么意思: Fast Forward Moving Picture Experts Group ffmpeg相关文档: Documentation FFmpeg ffmpeg源码下载: https://git.videolan.org/git/ffmpeg.git https://github.com/FFmpeg/FFmpeg.git FFmpeg能做什么? 多种媒体格式的封装与解封装 : 1.多种音…...

新版DBeaver调整编辑窗口字体大小

网上有DBeave字体设置了&#xff0c;但看了下&#xff0c;目前最新版的已经更改了首选项分组&#xff0c;层级发生了变化&#xff0c;这里记录一下2022.08.21版的设置。 默认字体是10&#xff0c;比较小&#xff0c;改为11或更大会好看些。...

《vue3实战》运用push()方法实现电影评价系统的添加功能

目录 前言 电影评价系统的添加功能是什么&#xff1f; 电影评价系统的添加功能有什么作用&#xff1f; 一、push&#xff08;&#xff09;方法是什么&#xff1f;它有什么作用&#xff1f; 含义&#xff1a; 作用&#xff1a; 二、功能实现 这段是添加开始时点击按钮使…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

CTF show Web 红包题第六弹

提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框&#xff0c;很难让人不联想到SQL注入&#xff0c;但提示都说了不是SQL注入&#xff0c;所以就不往这方面想了 ​ 先查看一下网页源码&#xff0c;发现一段JavaScript代码&#xff0c;有一个关键类ctfs…...

逻辑回归:给不确定性划界的分类大师

想象你是一名医生。面对患者的检查报告&#xff08;肿瘤大小、血液指标&#xff09;&#xff0c;你需要做出一个**决定性判断**&#xff1a;恶性还是良性&#xff1f;这种“非黑即白”的抉择&#xff0c;正是**逻辑回归&#xff08;Logistic Regression&#xff09;** 的战场&a…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...

BLEU评分:机器翻译质量评估的黄金标准

BLEU评分&#xff1a;机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域&#xff0c;衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标&#xff0c;自2002年由IBM的Kishore Papineni等人提出以来&#xff0c;…...