目录
前言
一、什么是数组
二、数组的顺序存储
1.定义
2.初始化
3.销毁数组
4.获取指定下标的数据元素
5.给数组中的数据元素赋值
6.完整代码
前言
这篇文章主要介绍数组的顺序存储。
一、什么是数组
数组是由类型相同的数据元素构成的有序集合,每个元素成为数组元素。数组元素在线性表中的序号称为改数据元素的下标。数组可以看成是线性表的推广,其特点是结构中的元素本身可以是某种结构的数据,但是都属于同一种数据类型。
图1.数组示意图
数组的基本操作有:初始化、销毁、赋值、取值操作。
二、数组的顺序存储
多维数组有两种存储方式:
1.以列为主序的存储方式
2.以行为主序的存储方式
两种存储方式示意图分别如下图所示:
图2.数组的两种存储方式
多维数组的存储位置遵循以下规则:
图3.多维数组的存储关系
数组的常用操作表示如下:
1.定义
typedef int ElemType;
typedef int Status;
#define MAX_ARRAY_DIM 8 // 假设数组维数的最大值为8
typedef struct {
ElemType* base; // 数组元素基址,由InitArray分配
int dim; // 数组维数
int* bounds; // 数组维界基址,由InitArray分配
int* constants; // 数组映像函数常量基址,由InitArray分配
} Array;
2.初始化
// 若维数dim和随后的各维度长度合法,则构造数组并返回构造成功的数组
Status InitArray(Array* arr, int dim, ...) {
if (dim < 1 || dim > MAX_ARRAY_DIM) return 0; // 维数不合法
// 分配内存并初始化维度信息
arr->dim = dim;
arr->bounds = (int*)malloc(dim * sizeof(int));
if (!arr->bounds) {
fprintf(stderr, "Memory allocation failed\n");
exit(EXIT_FAILURE);
}
arr->constants = (int*)malloc(dim * sizeof(int));
if (!arr->constants) {
fprintf(stderr, "Memory allocation failed\n");
exit(EXIT_FAILURE);
}
// 使用可变参数设置各维度长度,并计算总元素个数
int* ptr = &dim; // 使用可变参数需要定义指针
ptr++; // 指向维数之后的第一个参数
int totalElements = 1;
for (int i = 0; i < dim; i++) {
arr->bounds[i] = *ptr++; // 设置各维度长度
totalElements *= arr->bounds[i]; // 计算总元素个数
}
// 分配内存并初始化数组元素
arr->base = (ElemType*)malloc(totalElements * sizeof(ElemType));
if (!arr->base) {
fprintf(stderr, "Memory allocation failed\n");
exit(EXIT_FAILURE);
}
// 计算映像函数常量
arr->constants[dim - 1] = 1; // 最后一个维度的映像函数常量为1
for (int i = dim - 2; i >= 0; i--) {
arr->constants[i] = arr->bounds[i + 1] * arr->constants[i + 1]; // 计算其他维度的映像函数常量
}
return 1;
}
3.销毁数组
// 销毁数组
void DestroyArray(Array* arr) {
free(arr->base);
free(arr->bounds);
free(arr->constants);
}
4.获取指定下标的数据元素
// 获取数组中指定索引位置的元素值
ElemType value(const Array* arr, int indices[]) {
int offset = 0; // 计算元素在一维数组中的偏移量
// 根据索引计算偏移量
for (int i = 0; i < arr->dim; i++) {
if (indices[i] < 0 || indices[i] >= arr->bounds[i]) {
fprintf(stderr, "Index out of bounds\n");
exit(EXIT_FAILURE);
}
offset += arr->constants[i] * indices[i]; // 计算偏移量
}
return arr->base[offset]; // 返回对应位置的元素值
}
5.给数组中的数据元素赋值
// 将数组中指定索引位置的元素赋值为给定值
void assign(Array* arr, int indices[], ElemType value) {
int offset = 0; // 计算元素在一维数组中的偏移量
// 根据索引计算偏移量
for (int i = 0; i < arr->dim; i++) {
if (indices[i] < 0 || indices[i] >= arr->bounds[i]) {
fprintf(stderr, "Index out of bounds\n");
exit(EXIT_FAILURE);
}
offset += arr->constants[i] * indices[i]; // 计算偏移量
}
arr->base[offset] = value; // 将指定位置的元素赋值为给定值
}
6.完整代码
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
typedef int ElemType;
typedef int Status;
#define MAX_ARRAY_DIM 8 // 假设数组维数的最大值为8
typedef struct {
ElemType* base; // 数组元素基址,由InitArray分配
int dim; // 数组维数
int* bounds; // 数组维界基址,由InitArray分配
int* constants; // 数组映像函数常量基址,由InitArray分配
} Array;
// 若维数dim和随后的各维度长度合法,则构造数组并返回构造成功的数组
Status InitArray(Array* arr, int dim, ...) {
if (dim < 1 || dim > MAX_ARRAY_DIM) return 0; // 维数不合法
// 分配内存并初始化维度信息
arr->dim = dim;
arr->bounds = (int*)malloc(dim * sizeof(int));
if (!arr->bounds) {
fprintf(stderr, "Memory allocation failed\n");
exit(EXIT_FAILURE);
}
arr->constants = (int*)malloc(dim * sizeof(int));
if (!arr->constants) {
fprintf(stderr, "Memory allocation failed\n");
exit(EXIT_FAILURE);
}
// 使用可变参数设置各维度长度,并计算总元素个数
int* ptr = &dim; // 使用可变参数需要定义指针
ptr++; // 指向维数之后的第一个参数
int totalElements = 1;
for (int i = 0; i < dim; i++) {
arr->bounds[i] = *ptr++; // 设置各维度长度
totalElements *= arr->bounds[i]; // 计算总元素个数
}
// 分配内存并初始化数组元素
arr->base = (ElemType*)malloc(totalElements * sizeof(ElemType));
if (!arr->base) {
fprintf(stderr, "Memory allocation failed\n");
exit(EXIT_FAILURE);
}
// 计算映像函数常量
arr->constants[dim - 1] = 1; // 最后一个维度的映像函数常量为1
for (int i = dim - 2; i >= 0; i--) {
arr->constants[i] = arr->bounds[i + 1] * arr->constants[i + 1]; // 计算其他维度的映像函数常量
}
return 1;
}
// 销毁数组
void DestroyArray(Array* arr) {
free(arr->base);
free(arr->bounds);
free(arr->constants);
}
// 获取数组中指定索引位置的元素值
ElemType value(const Array* arr, int indices[]) {
int offset = 0; // 计算元素在一维数组中的偏移量
// 根据索引计算偏移量
for (int i = 0; i < arr->dim; i++) {
if (indices[i] < 0 || indices[i] >= arr->bounds[i]) {
fprintf(stderr, "Index out of bounds\n");
exit(EXIT_FAILURE);
}
offset += arr->constants[i] * indices[i]; // 计算偏移量
}
return arr->base[offset]; // 返回对应位置的元素值
}
// 将数组中指定索引位置的元素赋值为给定值
void assign(Array* arr, int indices[], ElemType value) {
int offset = 0; // 计算元素在一维数组中的偏移量
// 根据索引计算偏移量
for (int i = 0; i < arr->dim; i++) {
if (indices[i] < 0 || indices[i] >= arr->bounds[i]) {
fprintf(stderr, "Index out of bounds\n");
exit(EXIT_FAILURE);
}
offset += arr->constants[i] * indices[i]; // 计算偏移量
}
arr->base[offset] = value; // 将指定位置的元素赋值为给定值
}
int main(int argc, const char *argv[]) {
// 初始化数组
Array arr;
if (InitArray(&arr, 2, 3, 4)) { // 三行四列数组
printf("Array initialized successfully!\n");
// 给数组赋值并打印
printf("Assigning values to array elements and printing...\n");
for (int i = 0; i < 3; i++) { // 遍历行
for (int j = 0; j < 4; j++) { // 遍历列
int indices[2] = {i, j}; // 当前元素的索引
int value = i * 10 + j; // 计算要赋的值
assign(&arr, indices, value); // 赋值
printf("arr[%d][%d] = %d\n", i, j, value); // 打印赋值信息
}
}
// 打印数组元素
printf("\nArray elements after assignment:\n");
for (int i = 0; i < 3; i++) { // 遍历行
for (int j = 0; j < 4; j++) { // 遍历列
int indices[2] = {i, j}; // 当前元素的索引
printf("%d ", value(&arr, indices)); // 打印当前元素的值
}
printf("\n"); // 换行
}
// 销毁数组
DestroyArray(&arr);
printf("\nArray destroyed!\n");
} else {
printf("Array initialization failed!\n");
}
return 0;
}