第 5 章 数组和广义表(数组的顺序存储结构实现)

news2024/9/26 5:25:00

1. 背景说明

数组一旦被定义,它的维数和维界就不再改变。因此,除了结构的初始化和销毁之外,数组只有存取元素和修改元素值的操作。

2. 示例代码

1) status.h

/* DataStructure 预定义常量和类型头文件 */
#include <string.h>

#ifndef STATUS_H
#define STATUS_H

#define NONE ""

#define FILE_NAME(X) strrchr(X, '\\') ? strrchr(X,'\\') + 1 : X

#define DEBUG

#define CHECK_NULL(pointer) if (!(pointer)) { \
	printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_NULL_PTR); \
	return NULL; \
}

#define CHECK_FALSE(value, ERR_CODE) if (!(value)) { \
	printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_CODE); \
	return FALSE; \
}

#ifdef DEBUG
#define CHECK_RET(ret, FORMAT, ...) if (ret != RET_OK) { \
		printf("FileName: %-20s FuncName: %-15s Line: %-5d ErrorCode: %-3d" FORMAT "\n", FILE_NAME(__FILE__), __func__, __LINE__, ret, ##__VA_ARGS__); \
		return ret; \
	}
#else
#define CHECK_RET(ret, FORMAT, ...)
#endif

#ifdef DEBUG
#define CHECK_VALUE(value, ERR_CODE, FORMAT, ...) if (value) { \
		printf("FileName: %-20s FuncName: %-15s Line: %-5d ErrorCode: %-3d" FORMAT "\n", FILE_NAME(__FILE__), __func__, __LINE__, ERR_CODE, ##__VA_ARGS__); \
		return ERR_CODE; \
	}
#else
#define CHECK_VALUE(value, ERR_CODE, FORMAT, ...)
#endif

/* 函数结果状态码 */
#define TRUE 					1			/* 返回值为真 */
#define FALSE 					0			/* 返回值为假 */
#define RET_OK 					0			/* 返回值正确 */
#define ERR_MEMORY     		   	2			/* 访问内存错 */
#define ERR_NULL_PTR   			3			/* 空指针错误 */
#define ERR_MEMORY_ALLOCATE		4			/* 内存分配错 */
#define ERR_NULL_STACK			5			/* 栈元素为空 */
#define ERR_PARA				6			/* 函数参数错 */
#define ERR_OPEN_FILE			7			/* 打开文件错 */
#define ERR_NULL_QUEUE			8			/* 队列为空错 */
#define ERR_FULL_QUEUE			9			/* 队列为满错 */
#define ERR_NOT_FOUND			10			/* 表项不存在 */
typedef int Status;							/* Status 是函数的类型,其值是函数结果状态代码,如 RET_OK 等 */
typedef int Bollean;						/* Boolean 是布尔类型,其值是 TRUE 或 FALSE */

#endif // !STATUS_H

2) sqArray.h

/* 数组的顺序存储表示头文件 */

#ifndef SQ_ARRAY_H
#define SQ_ARRAY_H

#include "status.h"

#define MAX_ARRAY_DIM 10

typedef int ElemType;

typedef struct {
	ElemType *base;
	int dim;
	int *bounds;
	int *constants;
} Array;

/*  若维数 dim 和各维长度合法,则构造相应的数组 *array,并返回 OK */
Status InitArray(int dim, Array *array, ...);

/* 销毁数组 *array */
Status DestroyArray(Array *array);

/* 若 ap 指示的各下标值合法,则求出该元素在 *array 中的相对地址 *off */
Status Locate(va_list ap, const Array *array, int *off);

/* 若各维度的数组的下标值合法,则将数组相应元素值赋值给 *e */
Status GetArrayValue(const Array *array, ElemType *e, ...);

/* 若各维度的数组的下标值合法,则将元素值 e 赋值给数组相应元素 */
Status AssignArray(ElemType e, Array *array, ...);

#endif

3) sqArray.c

/* 数组的顺序存储实现源文件 */

#include "sqArray.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

/*  若维数 dim 和各维长度合法,则构造相应的数组 *array,并返回 OK */
Status InitArray(int dim, Array *array, ...)
{
	CHECK_VALUE(!array, ERR_NULL_PTR, NONE);
	CHECK_VALUE((dim < 1) || (dim > MAX_ARRAY_DIM), ERR_PARA, "dim = %d", dim);
	array->dim = dim;
	array->bounds = (int *)malloc(sizeof(int) * dim);
	CHECK_VALUE(!(array->bounds), ERR_MEMORY_ALLOCATE, NONE);
	va_list ap;
	va_start(ap, array);
	int elemTotal = 1;
	for (int i = 0; i < dim; ++i) {
		array->bounds[i] = va_arg(ap, int);
		CHECK_VALUE(array->bounds[i] < 0, ERR_PARA, "array->bounds[%d] = %d", i, array->bounds[i]);
		elemTotal *= array->bounds[i];
	}

	va_end(ap);
	array->base = (ElemType *)malloc(sizeof(ElemType) * elemTotal);
	CHECK_VALUE(!(array->base), ERR_MEMORY_ALLOCATE, NONE);
	array->constants = (int *)malloc(sizeof(int) * dim);
	CHECK_VALUE(!(array->constants), ERR_MEMORY_ALLOCATE, NONE);
	array->constants[dim - 1] = 1;
	for (int i = dim - 2; i >= 0; --i) {
		array->constants[i] = array->bounds[i + 1] * array->constants[i + 1];
	}

	return RET_OK;
}

/* 销毁数组 *array */
Status DestroyArray(Array *array)
{
	CHECK_VALUE(!array, ERR_NULL_PTR, NONE);
	free(array->base);
	free(array->bounds);
	free(array->constants);
	array->base = array->bounds = array->constants = NULL;
	array->dim = 0;

	return RET_OK;
}

/* 若 ap 指示的各下标值合法,则求出该元素在 *array 中的相对地址 *off */
Status Locate(va_list ap, const Array *array, int *off)
{
	CHECK_VALUE(!array || !off, ERR_NULL_PTR, NONE);
	int ind;
	*off = 0;
	for (int i = 0; i < array->dim; ++i) {
		ind = va_arg(ap, int);
		CHECK_VALUE((ind < 0) || (ind >= array->bounds[i]), ERR_PARA, "ind = %d, array->bounds[%d] = %d",
			ind, i, array->bounds[i]);
		*off += (array->constants[i]) * ind;
	}

	return RET_OK;
}

/* 若各维度的数组的下标值合法,则将数组相应元素值赋值给 *e */
Status GetArrayValue(const Array *array, ElemType *e, ...)
{
	CHECK_VALUE(!array || !e, ERR_NULL_PTR, NONE);
	va_list ap;
	va_start(ap, e);
	int off;
	Status ret = Locate(ap, array, &off);
	CHECK_VALUE(ret != RET_OK, ret, NONE);
	*e = *(array->base + off);

	return RET_OK;
}

/* 若各维度的数组的下标值合法,则将元素值 e 赋值给数组相应元素 */
Status AssignArray(ElemType e, Array *array, ...)
{
	CHECK_VALUE(!array, ERR_NULL_PTR, NONE);
	va_list ap;
	va_start(ap, array);
	int off;
	Status ret = Locate(ap, array, &off);
	CHECK_VALUE(ret != RET_OK, ret, NONE);
	*(array->base + off) = e;
	return RET_OK;
}

4) main.c

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

int main(void)
{
	/* 数组 array[3][4][2] */
	Array array;
	int dim = 3, bound1 = 3, bound2 = 4, bound3 = 2;
	Status ret = InitArray(dim, &array, bound1, bound2, bound3);
	CHECK_RET(ret, NONE);
	int *p = array.bounds;
	for (int i = 0; i < dim; ++i) {
		printf("array.bound[%d] = %d ", i, *(p + i));
	}

	printf("\n");
	p = array.constants;
	for (int i = 0; i < dim; ++i) {
		printf("array.constants[%d] = %d ", i, *(p + i));
	}

	printf("\n\n%d pages %d row %d col element: \n", bound1, bound2, bound3);
	ElemType e;
	for (int i = 0; i < bound1; ++i) {
		for (int j = 0; j < bound2; ++j) {
			for (int k = 0; k < bound3; ++k) {
				ret = AssignArray(i * 100 + j * 10 + k, &array, i, j, k);
				ret |= GetArrayValue(&array, &e, i, j, k);
				CHECK_RET(ret, "i = %d, j = %d, k = %d", i, j, k);
				printf("  array[%d][%d][%d] = %3d", i, j, k, e);
			}

			printf("\n");
		}

		printf("\n");
	}

	ElemType *p1 = array.base;
	printf("array.base = \n");
	for (int i = 0; i < bound1 * bound2 * bound3; ++i) {
		printf("%22d", *(p1 + i));
		if (i % 2 == 1) {
			printf("\n");
		}
	}

	ret = DestroyArray(&array);
	CHECK_RET(ret, NONE);

	return RET_OK;
}

3. 输出示例

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

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

相关文章

【论文精读】Chain-of-Thought Prompting Elicits Reasoning in Large Language Models

Chain-of-Thought Prompting Elicits Reasoning in Large Language Models 前言Abstract1 Introduction2 Chain-of-Thought Prompting3 Arithmetic Reasoning3,1 Experimental Setup3.2 Results3.3 Ablation Study3.4 Robustness of Chain of Thought 4 Commonsense Reasoning5…

通过Java Record提升代码质量:简洁而健壮的数据对象

为了提高开发效率和代码可读性&#xff0c;Java 14引入了一个新的特性 - Records&#xff08;记录类型&#xff09;。Records旨在简化和改进Java中的数据类定义&#xff0c;使得创建简单的数据传输对象&#xff08;DTO&#xff09;或值对象更加便捷。 什么是Java Record&#x…

Springboot接收http参数总结(最简单易懂)

1. 前端能携带请求参数的地方 http请求一半前端请求参数放在三个地方&#xff1a;请求头&#xff0c;请求查询参数&#xff08;Query String&#xff09;&#xff0c;请求体。 请求体需要获取HttpServletRequest对象才能获取。 2. 请求体常见格式 而请求体中可以存放多种格式…

Leetcode92. 反转链表 II

Every day a Leetcode 题目来源&#xff1a;92. 反转链表 II 解法1&#xff1a;模拟 注意 STL 的 reverse() 是左闭右开的。 代码&#xff1a; class Solution { public:ListNode *reverseBetween(ListNode *head, int left, int right){vector<int> nums getNums(…

Altium Designer 20.2.3导入自带的原理图库

看了几天的AD学习视频&#xff0c;把我看得晕头转向的&#xff0c;静整些没用的东西&#xff0c;浪费时间&#xff0c;画个原理图讲了好几天&#xff0c;就那么点东西&#xff0c;在那扯淡&#xff0c;有系统自带的库他不教你怎么用&#xff0c;故意藏着掖着。想叫学习的小伙伴…

抽象轻松的java——mybaties

前置工作http://t.csdnimg.cn/RVvn4完成了前置工作后的IDEA应该是这样的 正式进入mybaties的入门 第一步&#xff0c;打开mybaties的官网文档https://mybatis.net.cn/getting-started.html本次入门&#xff0c;将从XML构造SQL工厂 第一步&#xff0c;创建一个XML文件&#xf…

Java架构师主流架构设计模式

目录 1 主流架构设计模式1.1 分层架构模式1.1.1 分层架构的一些常见原则1.1.2 分层的单向依赖原则1.1.3 无循环依赖的原则1.1.4 避免跨层通信的原则1.2 微服务架构模式1.3 基于事件的架构模式2 整洁架构3 六边形架构4 微内核架构模式5 基于空间的架构模式6 道过滤器模式和代理模…

UE5中实现沿样条线创建网格体2-SplineMesh版本

我在之前的一篇文章中写过沿样条线创建网格体的方法&#xff1a; https://blog.csdn.net/grayrail/article/details/130453733 但该方法没有网格变形操作&#xff0c;就会导致每一段网格对象是无法连接的&#xff1a; 后来发现了SplineMesh方法可以比较好的解决这个问题&…

电子沙盘数字沙盘大数据人工智能开发教程第16课

电子沙盘数字沙盘大数据可视化GIS系统开发教程第16课&#xff1a;新增加属性在MTGIS3d控件 public bool ShowFLGrid;//是否显 示方里网格。 public bool Atmosphere;//是否显示大气圈。&#xff08;因为WPF不支持shader功能&#xff0c;所以效果嘛。。。&#xff09; 在SDK中为…

ACK 云原生 AI 套件:云原生 AI 工程化落地最优路径

作者&#xff1a;胡玉瑜(稚柳) 前言 在过去几年中&#xff0c;人工智能技术取得了突飞猛进的发展&#xff0c;涵盖了机器学习、深度学习和神经网络等关键技术的重大突破&#xff0c;这使得人工智能在各个领域都得到广泛应用&#xff0c;对各行各业产生了深远的影响。 特别值…

Springcloud中间件-----分布式搜索引擎 Elasticsearch

该笔记是根据黑马程序员的课来自己写了一遍的,b站有对应教程和资料 第一部分 第二部分 第三部分 预计看完跟着练习5小时足够 1.初识elasticsearch 1.1.了解ES 1.1.1.elasticsearch的作用 elasticsearch是一款非常强大的开源搜索引擎&#xff0c;具备非常多强大功能&#xff…

【调试工具|mqtt-spy】mqtt客户端调试工具 mqtt-spy 详细使用教程

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…

数据分析:小红书“情绪营销”如何拿捏年轻人

导语 小红书话题#不扫兴养成计划#上线&#xff0c;近30天话题浏览量破5000W&#xff0c;同比增长418.19%&#xff0c;数据表现良好。 图 | 千瓜数据 什么是不扫兴养成&#xff1f; 定义&#xff1a;想了解“不扫兴”的意思&#xff0c;那就先来看看它的反义“扫兴”吧。“扫…

2023版 STM32实战9 RTC实时时钟/闹钟

RTC简介 实时时钟是一个独立的定时器。RTC模块拥有一组连续计数的计数器&#xff0c;在相应软件配置下&#xff0c;可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。 注意事项 -1- 要手动配置中断寄存器 -2- 需要等待写操作完成 -3- 时钟闹钟中段…

JVM 性能监控与故障处理工具

基础工具 jps&#xff1a;虚拟机进程状态工具 jps 命令格式&#xff1a;jps [options] [hostid] 命令可选项解释&#xff1a; 选项解释-q只输出 LVMID&#xff0c;省略主类的名称-m输出传给 main 函数的参数-l输出主类的全名&#xff0c;如果进程运行的 JAR 包&#xff0c;…

ESP8266 WiFi物联网智能插座—下位机软件实现

目录 1、软件架构 2、开发环境 3、软件功能 4、程序设计 4.1、初始化 4.2、主循环状态机 4.3、初始化模式 4.4、配置模式 4.5、运行模式 4.6、重启模式 4.7、升级模式 5、程序功能特点 5.1、日志管理 5.2、数据缓存队列 本篇博文开始讲解下位机插座节点的MCU软件…

淘宝京东拼多多商品价格采集分析接口

淘宝、京东、拼多多商品价格采集分析接口的具体信息&#xff0c;但是可以为您提供一些参考内容&#xff1a; 登录京东、天猫、淘宝、拼多多、苏宁、国美、唯品会等电商平台&#xff0c;注册并获取开发者账号和API接口权限。通过开发者账号和API接口权限&#xff0c;访问京东、…

Java之实现添加文字水印、图片水印功能

文章目录 1 添加文字水印、图片水印1.1 给图片添加文字水印1.1.1 获取原图片对象信息1.1.1.1 读取本地图片1.1.1.2 读取网络图片 1.1.2 添加水印1.1.3 确定水印位置1.1.3.1 设置固定值1.1.3.2 根据原图大小进行设置 1.1.4 获取目标图片1.1.5 完整代码 1.2 java实现给图片添加图…

HomeView/主页 的实现

1. 创建数据模型 1.1 创建货币模型 CoinModel.swift import Foundation// GoinGecko API info /*URL:https://api.coingecko.com/api/v3/coins/markets?vs_currencyusd&ordermarket_cap_desc&per_page250&page1&sparklinetrue&price_change_percentage24…

论文中的小细节——为什么论文中总是写WX而不是XW?

这是最近一个师弟问我的问题&#xff0c;为什么在论文里面总是写的 Y W X YWX YWX&#xff0c;而不是 Y X W YXW YXW&#xff1f;就算有的时候需要转置 W W W 或者 X X X&#xff0c;都不写 Y X W YXW YXW&#xff1f; 这个问题我最开始回答的是这就是约定俗成的写法&…