第 2 章 线性表 (线性表的静态单链表存储结构(一个数组只生成一个静态链表)实现)

news2024/11/24 13:02:10

1. 背景说明

A = { c, b, e, g, f, d }

B = { a, b, n, f }

2. 示例代码 

1) status.h

/* DataStructure 预定义常量和类型头文件 */

#ifndef STATUS_H
#define STATUS_H

#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) staticLinkListSingle.h

/* 静态链表(一个数组只生成一个静态链表)实现头文件 */

#ifndef STATICLINKLISTSINGLE_H
#define STATICLINKLISTSINGLE_H

#include "status.h"

#define MAX_SIZE 100

typedef int ElemType;

typedef struct {
	ElemType data;
	int curr;
} SLinkList[MAX_SIZE];

/* 若备用链表非空,则返回分配的结点下标(备用链表的第一个结点),否则返回 0 */
int Malloc(SLinkList space);

/* 将下标为 i 的空闲结点回收到备用链表(成为备用链表的第一个结点) */
void Free(SLinkList space, int i);

/* 静态数组无法被销毁 */
void DestroyList(void);

/* 构造一个空的链表,表头为 L 的最后一个单元 L[MAXSIZE - 1],其余单元链成
   一个备用链表,表头为 L 的第一个单元 L[0],'0' 表示空指针 */
void InitList(SLinkList L);

/* 初始条件:线性表 L 已存在
   操作结果:将 L 重置为空表 */
Status ClearList(SLinkList L);

/* 若 L 是空表,返回 TRUE;否则返回 FALSE */
Bollean ListEmpty(SLinkList L);

/* 返回 L 中数据元素个数 */
int ListLength(SLinkList L);

/* 用 e 返回 L 中第 i 个元素的值 */
Status GetElem(SLinkList L, int i, ElemType *e);

/* 算法 2.13, 在静态单链线性表 L 中查找第 1 个值为 e 的元素。若找到,则返回它
   在 L 中的位序,否则返回 0 */
int LocateElem(SLinkList L, ElemType e);

/* 初始条件:线性表 L 已存在
   操作结果:若 curr_e 是 L 的数据元素,且不是第一个,则用 pre_e返回它的前驱否
   则操作失败,pre_e 无定义 */
Status PriorElem(SLinkList L, ElemType curr_e, ElemType *pre_e);

/* 初始条件:线性表 L 已存在
   操作结果:若 curr_e 是 L 的数据元素,且不是最后一个,则用 next_e 返回它的后
   继, 否则操作失败,next_e 无定义 */
Status NextElem(SLinkList L, ElemType curr_e, ElemType *next_e);

/* 在 L 中第 i 个元素之前插入新的数据元素 e */
Status ListInsert(SLinkList L, int i, ElemType e);

/* 删除在 L 中第 i 个数据元素 e,并返回其值 */
Status ListDelete(SLinkList L, int i, ElemType *e);

/* 初始条件: 线性表 L 已存在
   操作结果: 依次对 L 的每个数据元素调用函数 vi()。一旦 vi() 失败, 则操作失败 */
Status ListTraverse(SLinkList L, void(*vi)(ElemType));

#endif

3) staticLinkListSingle.c

/* 静态链表(一个数组只生成一个静态链表)实现源文件 */

#include "staticLinkListSingle.h"
#include <stdio.h>

/* 若备用链表非空,则返回分配的结点下标(备用链表的第一个结点),否则返回 0 */
int Malloc(SLinkList space)
{
	int i = space[0].curr;
	if (i) {
		space[0].curr = space[i].curr;
	}

	return i;
}

/* 将下标为 i 的空闲结点回收到备用链表(成为备用链表的第一个结点) */
void Free(SLinkList space, int i)
{
	space[i].curr = space[0].curr;
	space[0].curr = i;
}

/* 静态数组无法被销毁 */
void DestroyList(void)
{
	printf("Static array do not need to free memory!\n");
}

/* 构造一个空的链表,表头为 L 的最后一个单元 L[MAXSIZE - 1],其余单元链成
   一个备用链表,表头为 L 的第一个单元 L[0],'0' 表示空指针 */
void InitList(SLinkList L)
{
	L[MAX_SIZE - 1].curr = 0;
	for (int i = 0; i < MAX_SIZE - 2; ++i) {
		L[i].curr = i + 1;
	}

	L[MAX_SIZE - 2].curr = 0;
}

/* 初始条件:线性表 L 已存在
   操作结果:将 L 重置为空表 */
Status ClearList(SLinkList L)
{
	int i = L[MAX_SIZE - 1].curr;
	L[MAX_SIZE - 1].curr = 0;
	int k = L[0].curr;
	L[0].curr = i;
	int j;
	while (i) {
		j = i;
		i = L[i].curr;
	}

	L[j].curr = k;

	return RET_OK;
}

/* 若 L 是空表,返回 TRUE;否则返回 FALSE */
Bollean ListEmpty(SLinkList L)
{
	return (L[MAX_SIZE - 1].curr == 0) ? TRUE : FALSE;
}

/* 返回 L 中数据元素个数 */
int ListLength(SLinkList L)
{
	int length = 0;
	int i = L[MAX_SIZE - 1].curr;
	while (i) {
		i = L[i].curr;
		++length;
	}

	return length;
}

/* 用 e 返回 L 中第 i 个元素的值 */
Status GetElem(SLinkList L, int i, ElemType *e)
{
	CHECK_VALUE(((i < 1) || (i > ListLength(L))), ERR_PARA)
	int head = MAX_SIZE - 1;
	for (int j = 0; j < i; ++j) {
		head = L[head].curr;
	}

	*e = L[head].data;

	return RET_OK;
}

/* 算法 2.13, 在静态单链线性表 L 中查找第 1 个值为 e 的元素。若找到,则返回它
   在 L 中的位序,否则返回 0 */
int LocateElem(SLinkList L, ElemType e)
{
	int i = L[MAX_SIZE - 1].curr;
	while ((i) && (L[i].data != e)) {
		i = L[i].curr;
	}

	return i;
}

/* 初始条件:线性表 L 已存在
   操作结果:若 curr_e 是 L 的数据元素,且不是第一个,则用 pre_e返回它的前驱否
   则操作失败,pre_e 无定义 */
Status PriorElem(SLinkList L, ElemType curr_e, ElemType *pre_e)
{
	int i = L[MAX_SIZE - 1].curr;
	int j;
	do {
		j = i;
		i = L[i].curr;
	} while ((i) && (L[i].data != curr_e));

	if (i) {
		*pre_e = L[j].data;
		return RET_OK;
	}

	printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_NOT_FOUND);

	return ERR_NOT_FOUND;
}

/* 初始条件:线性表 L 已存在
   操作结果:若 curr_e 是 L 的数据元素,且不是最后一个,则用 next_e 返回它的后
   继, 否则操作失败,next_e 无定义 */
Status NextElem(SLinkList L, ElemType curr_e, ElemType *next_e)
{
	int i = LocateElem(L, curr_e);
	int j;
	if (i) {
		j = L[i].curr;
		if (j) {
			*next_e = L[j].data;
			return RET_OK;
		}
	}

	printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_NOT_FOUND);

	return ERR_NOT_FOUND;
}

/* 在 L 中第 i 个元素之前插入新的数据元素 e */
Status ListInsert(SLinkList L, int i, ElemType e)
{
	CHECK_VALUE((i < 1) || i > ListLength(L) + 1, ERR_PARA)
	int j = Malloc(L);
	CHECK_VALUE(!j, ERR_MEMORY_ALLOCATE)
	L[j].data = e;
	int head = MAX_SIZE - 1;
	for (int k = 0; k < i - 1; ++k) {
		head = L[head].curr;
	}

	L[j].curr = L[head].curr;
	L[head].curr = j;

	return RET_OK;
}

/* 删除在 L 中第 i 个数据元素 e,并返回其值 */
Status ListDelete(SLinkList L, int i, ElemType *e)
{
	CHECK_VALUE((i < 1) || i > ListLength(L), ERR_PARA)
	int head = MAX_SIZE - 1;
	int j;
	for (j = 0; j < i - 1; ++j) {
		head = L[head].curr;
	}

	j = L[head].curr;
	L[head].curr = L[j].curr;
	*e = L[j].data;
	Free(L, j);

	return RET_OK;
}

/* 初始条件: 线性表 L 已存在
   操作结果: 依次对 L 的每个数据元素调用函数 vi()。一旦 vi() 失败, 则操作失败 */
Status ListTraverse(SLinkList L, void(*vi)(ElemType))
{
	int i = L[MAX_SIZE - 1].curr;
	while (i) {
		vi(L[i].data);
		i = L[i].curr;
	}

	return RET_OK;
}

4) main.c

#include "staticLinkListSingle.h"
#include <stdio.h>

void Visit(ElemType e);

int main(void)
{
	SLinkList L;
	InitList(L);
	for (int i = 0; i < 5; ++i) {
		ListInsert(L, 1, i + 1);
	}

	printf("After insert 1 ~ 5 in head of L, L is: ");
	ListTraverse(L, Visit);
	putchar('\n');
	printf("L is %s, the length of L is %d\n", ((ListEmpty(L) == TRUE) ? "empty" : "not empty"),
		ListLength(L));
	ClearList(L);
	printf("After clear L, L is: ");
	ListTraverse(L, Visit);
	putchar('\n');
	printf("L is %s, the length of L is %d\n", ((ListEmpty(L) == TRUE) ? "empty" : "not empty"),
		ListLength(L));
	for (int i = 0; i < 10; ++i) {
		ListInsert(L, i + 1, i + 1);
	}

	printf("After insert 1 ~ 10 in tail of L, L is: ");
	ListTraverse(L, Visit);
	putchar('\n');
	ElemType e;
	GetElem(L, 5, &e);
	printf("The %dth element of L is %d\n", 5, e);
	for (int i = 0; i < 2; ++i) {
		int pos = LocateElem(L, i);
		if (pos) {
			printf("The order of element %d in L is %d\n", i, pos);
		} else {
			printf("Element %d is not exist in L\n", i);
		}
	}

	for (int i = 1; i < 3; ++i) {
		ElemType e, prior;
		GetElem(L, i, &e);
		Status ret = PriorElem(L, e, &prior);
		if (ret == RET_OK) {
			printf("The previous element of %d is %d\n", e, prior);
		} else {
			printf("The previous element of %d is not exist.\n", e);
		}
	}

	for (int i = ListLength(L) - 1; i <= ListLength(L); ++i) {
		ElemType e, next;
		GetElem(L, i, &e);
		Status ret = NextElem(L, e, &next);
		if (ret == RET_OK) {
			printf("The next element of %d is %d\n", e, next);
		} else {
			printf("The next element of %d is not exist.\n", e);
		}
	}

	int length = ListLength(L);
	for (int i = length + 1; i >= length; --i) {
		ElemType e;
		Status ret = ListDelete(L, i, &e);
		if (ret == RET_OK) {
			printf("The element deleted is %d\n", e);
		} else {
			printf("Delete %dth element failed!\n", i);
		}
	}

	printf("Now, the element in L is: ");
	ListTraverse(L, Visit);
	putchar('\n');

	DestroyList();

	return 0;
}

void Visit(ElemType e)
{
	printf("%d ", e);
}

3. 运行示例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/989453.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Redis】Lua脚本在Redis中的基本使用及其原子性保证原理

文章目录 背景一、Eval二、EvalSHA三、Redis 对 Lua 脚本的管理3.1 script flush3.2 script exists3.3 script load3.4 script kill 四、Lua在Redis中原子性执行的原理 背景 Lua 本身是一种轻量小巧的脚本语言&#xff0c;在Redis2.6版本开始引入了对Lua脚本的支持。通过在服务…

高并发环境下压测故障

文章目录 一、高并发压测故障二、JVM 调优1. 堆内存调优2. 堆外内存调优 一、高并发压测故障 每次在大促之前&#xff0c;我们都需要对服务进行压测。而在压测期间&#xff0c;突然爆发了红灯告警&#xff0c;订单量直接少了一半&#xff0c;这是一次很严重的压测故障。首先看…

公司快递账单管理智能化教程

今时不同往日&#xff0c;企业寄件早已摆脱纸质面单&#xff0c;向更为便捷的电子面单过渡。众快递公司为了留住大客户&#xff0c;为其提供更好的服务&#xff0c;早早推出月结模式寄件。办公族应该不陌生&#xff0c;企业如果和快递公司签订月结协议的话&#xff0c;员工寄件…

SEO扫地僧站群·静态生成式养站王,万站秒建,批量养站神器介绍

扫地僧站群静态养站王,程序采用了"织梦CMS"式静态生成式的方式&#xff0c;只需要一个后台管理系统即可管理多个网站&#xff0c;大大提高了建站效率,程序可以适配各种采集器获得的内容&#xff0c;可以方便地实现内容的快速采集,程序支持实时统计和广告插入&#xf…

leetcode刷题--栈与递归

文章目录 1. 682 棒球比赛2. 71 简化路径3. 388 文件的最长绝对路径4. 150 逆波兰表达式求值5. 227. 基本计算器II6. 224. 基本计算器7. 20. 有效的括号8. 636. 函数的独占时间9. 591. 标签验证器10. 32.最长有效括号12. 341. 扁平化嵌套列表迭代器13. 394.字符串解码 1. 682 棒…

docker 部署vue

1&#xff1a; 首先部署nginx docker run --name nginx -d -p 88:80 nginx 2&#xff1a;访问 http://xxxxxxx:88/ 3: 进入nginx docker exec -it nginx /bin/sh 4: 回到vs&#xff0c;编译项目 npm run build 得到dist文件夹 5&#xff1a;创建docker 6&#xff1a; 将…

量化交易最新12篇顶会论文及开源代码汇总(WWW23、AAAI23、KDD23)

对比普通的交易方式&#xff0c;量化交易具有高效性、稳定性以及强风险控制能力&#xff0c;因此&#xff0c;量化交易在金融领域中已经得到了广泛的应用&#xff0c;目前已有许多大型投资机构和对冲基金将量化交易列为其投资组合的重要部分。 本次分享的是我从各大顶会中精选…

826. 安排工作以达到最大收益;2257. 统计网格图中没有被保卫的格子数;816. 模糊坐标

826. 安排工作以达到最大收益 核心思想&#xff1a;排序维护最大利润。首先我们需要对工人按照能力排序&#xff0c;前面工人满足的最大利润后面的工人肯定是满足的&#xff0c;所以我们只需要用一个tmp来维护小于等于当前工人的最大利润&#xff0c;然后如何得到tmp&#xff…

java.lang.Exception: No runnable methods

无可执行test方法异常&#xff0c;报错为&#xff1a; 1.查看是否添加了Test注解在执行的方法上 2.查看测试类的注解 3.查看test类的导包&#xff0c;一定要是junit的。

【SpringMVC】RESTful风格CRUD实现

目录 一、REST简介 1.1 什么是REST? 1.2 REST风格的优点 1.3 请求方式 二、构建项目 ⭐思路分析 2.1 环境准备 2.1.1 导入相关pom依赖 2.1.2 jdbc.properties&#xff1a;配置文件 2.1.3 配置代码生成器 generatorConfig.xml 2.1.4 spring与mybatis整合的配置文件 s…

开机性能-如何抓取开机systrace

一、理论 1.背景 抓取开机 trace 需要使用 userdebug 版本&#xff0c;而我们测试开机性能问题时都要求使用 user 版本&#xff0c;否则会有性能损耗问题。因此想要在抓取开机性能trace 时&#xff0c;需要在 user 版本上打开 atrace 功能之后才能抓取 trace&#xff0c;默认 …

什么是CE认证?CE认证如何办理?亚马逊欧洲站产品适用范围

什么是CE标志&#xff1f; CE标志是欧盟强制认证标志&#xff0c;代表着产品符合欧洲指令的基本要求。这意味着&#xff0c;只有经过认证并贴上CE标志&#xff0c;你的产品才能合法地进入欧洲市场销售。那么&#xff0c;如何让你的产品贴上CE标志呢&#xff1f;接着往下看。 如…

【刷题篇】贪心算法

文章目录 分割平衡字符串买卖股票的最佳时机Ⅱ跳跃游戏钱币找零 分割平衡字符串 class Solution { public:int balancedStringSplit(string s) {int lens.size();int cnt0;int balance0;for(int i0;i<len;i){if(s[i]R){balance--;}else{balance;}if(balance0){cnt;}}return …

作为程序员,如何快速上手项目

点击下方关注我&#xff0c;然后右上角点击...“设为星标”&#xff0c;就能第一时间收到更新推送啦~~~ 本节从“道、术、器”三个方面为大家分享程序员如何快速上手项目。 1 道 道&#xff0c;就是道理、规律&#xff0c;万事万物都有道&#xff0c;软件开发也有道。 软件开发…

strerror函数

目录 strerror 函数介绍&#xff1a; 举例&#xff1a; 使用案例&#xff1a; 优化&#xff1a; perror&#xff1a; strerror 函数介绍&#xff1a; 函数声明&#xff1a; char * strerror ( int errnum );头 文 件&#xff1a;#include <string.h>返 回 值&a…

基于 SpringBoot 的智慧养老平台,附源码、教程

文章目录 1.研究背景2. 技术栈3.系统分析4系统设计4.1 软件功能模块设计4.2数据库设计与实现 5系统详细设计5.1系统功能模块5.2后台登录功能5.2.1管理员功能 源码下载地址 1.研究背景 困扰管理层的许多问题当中,智慧养老平台一定是养老平台不敢忽视的一块。但是管理好智慧养老…

一.使用qt creator 设计显示GUI

一.安装qt creator 二.创建项目 文件-》新建项目 三.使用设计 可以直接使用鼠标拖拽 四.转换为py文件 # from123.py 为导出 py文件的文件名 form.ui 为 qt creator创造的 ui 文件 pyuic5 -o x:\xxx\from123.py form.ui五.显示GUI from PyQt5.QtWidgets import * fr…

【C进阶】指针(二)

六、函数指针数组 数组是一个存放相同类型数据的存储空间&#xff0c;我们已经学习了指针数组 eg&#xff1a; int *arr[10] //整形指针数组-数组-存放的是整形指针 char *arr[5] //字符指针数组-数组-存放的是字符指针 那么把函数的地址存到一个数组中&#xff0…

2023国赛A题保姆级思路代码:定日镜场的优化设计

A题是一套传统的机理分析加规划求解题&#xff0c;首先我们要根据每个月21号的特定时间点建立一个太阳角度框架&#xff0c;根据题目所给出的公式计算效率&#xff0c;还有输出的热功率&#xff0c;然后根据月份求解各种效率&#xff0c;再把年份进行汇总&#xff0c;二三题都是…

阿里国际、亚马逊等跨境电商平台做测评怎么避免踩坑?

由于跨境电商的卖家越来越多&#xff0c;测评逐渐成为众多卖家的关注焦点&#xff0c;在各个跨境电商平台上&#xff0c;随着店铺数量的增加&#xff0c;同一商品之间的竞争也日益激烈&#xff0c;不同于国内的电商平台&#xff0c;跨境电商平台很少提供与卖家客服进行沟通的机…