
点击上方蓝字关注我!
如果有错误或者理解不到位的地方还请各位指正!
数据结构的相关问题,可以参考笔者写的系列数据结构文章,或者加我交流!
声明:以下内容是对清华大学出版社出版,由严蔚敏和吴伟民编著的图书《数据结构》(C语言版)的代码实现。
图书PDF版本可移步公众号【李歘歘】回复电子书领取。
上次说到了队列的循环队列,今天我们来说一下有关数组的顺序数组,相关知识点可以先了解一下。
可以适当的先了解一下stdarg头文件写的三个宏:va_start、va_arg、va_end
书中位置(页码):P93-P95
函数定义及说明:
Status InitArray(Array &A, int dim,...) //初始化数组
Status DestoryArray(Array &A) //销毁数组
Status Locate(Array A,va_list ap,int &off) //获取元素下标对应的地址
Status Value(Array A,ElemType &e,...) //获取元素的值
Status Assgin(Array &A,ElemType e,...) //为元素赋值
复制
程序代码:
#include<cstdio>
#include<cstdlib>
#include<cstdarg> 标准头文件,提供三个宏(va_start、va_arg和va_end)
用于存取变长参数表
#define ElemType int
#define Status int
#define MAX_ARRAY_DIM 8 数组维数的最大值
typedef struct{
ElemType *base; 数组元素基址,由InitArray分配
int dim; 数组维数
int *bounds; 数组维界基址,由InitArray分配
*
假设数组的维数是3,每个维数的值分别为(2,3,4),则这相当于是嵌套数组
bounds[0] = 2 将数组分成两大部分
bounds[1] = 3 两大部分中,每一部分分为三部分(共六部分)
bounds[2] = 4 六部分中每一部分有4个值
array = (((x,x,x,x),(x,x,x,x),(x,x,x,x)),((x,x,x,x),(x,x,x,x),(x,x,x,x)))
*/
int *constants; 数组映像函数常量基址,由InitArray分配
*
就是每一个元素的在数组中的位置,如上面的三维数组元素需要24个元素位置
如 array[1][2][3]的地址为:3*4+2*4+3=24(就是最后一个元素的位置,数组小标从0开始)
*/
}Array;
//初始化数组
Status InitArray(Array &A, int dim,...){
//若维数dim和各维长度合法,则构造相应的数组A,并返回OK
if(dim < 1 || dim >MAX_ARRAY_DIM ){
printf("维数不合法\n");
return 0;
}
A.dim = dim;
A.bounds = (int *)malloc(dim * sizeof(int)); //分配大小为维数的命名空间,用于存储每一个维数的值,并返回基址
if(!A.bounds){
printf("存储空间分配失败\n");
return 0;
}
//若各维长度合法,则存入A.bounds,并求出A的元素总数elemtotal
int elemtotal = 1;
va_list ap; //ap为va_list类型,是存放变长参数表信息的数组
va_start(ap,dim); // 从dim后开始读取
for(int i=0;i<dim;i++){ //循环,为bounds赋值
A.bounds[i] = va_arg(ap,int); //从参数表中读取各个维数对应的值
if(A.bounds[i]<0) //如果维数输入为0,则错误
return 0;
elemtotal *= A.bounds[i]; //总数=维数对应值的乘积值
}
va_end(ap); //结束参数的读取
A.base = (ElemType *)malloc(elemtotal * sizeof(ElemType)); //分配大小为元素个数的命名空间,并返回基址
if(!A.base){
printf("存储空间分配失败\n");
return 0;
}
//求映像函数常量Ci,并存入A.constants[i-1],i=1~dim
A.constants = (int *)malloc(dim * sizeof(int));
/*分配大小为维数的命名空间,用于存储每一个维数元素的个数,并返回基址
例如 A.constants[0] = 12
A.constants[1] = 4
A.constants[2] = 1
*/
if(!A.constants){
printf("存储空间分配失败\n");
return 0;
}
A.constants[dim-1] = 1; //最后一维 L=1,指针的增减以元素的大小为单位
for(int i=dim-2;i>=0;--i) //循环给constants赋值
A.constants[i] = A.bounds[i+1] * A.constants[i+1];
printf("初始化成功\n");
return 0;
}
//销毁数组
Status DestoryArray(Array &A){
//销毁数组A
if(!A.base){
printf("销毁失败,未能找到元素基址\n");
return 0;
}
free(A.base); //释放基址空间
A.base = NULL; //数组元素基址置为空
if(!A.bounds){
printf("销毁失败,未能找到维界基址\n");
return 0;
}
free(A.bounds); //释放基址空间
A.bounds = NULL; //数组维界基址置为空
if(!A.constants){
printf("销毁失败,未能找到映像函数常量基址\n");
return 0;
}
free(A.constants); //释放基址空间
A.constants = NULL; //数组映像函数常量基址置为空
printf("销毁数组成功\n");
return 0;
}
//获取元素下标对应的地址
Status Locate(Array A,va_list ap,int &off){
//若ap指示的各下标值合法,则求出该元素在A中相对地址off
off = 0;
for(int i=0;i<A.dim;i++){
int ind = va_arg(ap,int);
if(ind<0 || ind>=A.bounds[i]){
printf("数组小标越界\n");
return 0;
}
//公式对应P92
off += A.constants[i]*ind; //每一维的小标程每一维的偏移量
}
}
//获取元素的值
Status Value(Array A,ElemType &e,...){
//A是n维数组,e为元素变量,随后是n个下标值
//若各下标不超界,则e赋值为所指定的A的元素值
va_list ap;
int off;
Status result;
va_start(ap,e);
if((result = Locate(A,ap,off))<=0){
return result;
}
e = *(A.base+off);
printf("值为:%d\n",e);
return 0;
}
//为元素赋值
Status Assgin(Array &A,ElemType e,...){
//A是n维数组,e为元素变量,随后是n个下标值
//若各下标不超界,则e赋值为所指定的A的元素值
va_list ap;
int off;
Status result;
va_start(ap,e);
if((result = Locate(A,ap,off))<=0){
return result;
}
*(A.base+off) = e;
printf("赋值为:%d成功\n",e);
return 0;
}
int main(){
Array array;
int value;
int dim = 3; //维数3
//初始化
InitArray(array,dim,2,3,4); //三个维数分别为2,3,4
printf("%d %d %d \n",array.bounds[0],array.bounds[1],array.bounds[2]);
printf("%d %d %d \n",array.constants[0],array.constants[1],array.constants[2]);
Assgin(array,666,1,2,3);
Value(array,value,1,2,3);
return 0;
}
复制
「往 • 期 • 精 • 选」
数据结构(严蔚敏C语言版)——线性表(静态链表)
数据结构(严蔚敏C语言版)——线性表(普通链表)


文章转载自编程Cookbook,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
2025年3月中国数据库排行榜:PolarDB夺魁傲群雄,GoldenDB晋位入三强
墨天轮编辑部
2021次阅读
2025-03-11 17:13:58
【专家有话说第五期】在不同年龄段,DBA应该怎样规划自己的职业发展?
墨天轮编辑部
1331次阅读
2025-03-13 11:40:53
11 【HarmonyOS NEXT】 仿uv-ui组件开发之Avatar组件深度剖析(二)
若城
1062次阅读
2025-03-07 21:35:16
10 【HarmonyOS NEXT】 仿uv-ui组件开发之Avatar头像组件开发教程(一)
若城
1061次阅读
2025-03-07 21:10:59
12 【HarmonyOS NEXT】 仿uv-ui组件开发之Avatar组件设计精髓(三)
若城
1052次阅读
2025-03-07 21:49:38
13 【HarmonyOS NEXT】 仿uv-ui组件开发之Avatar组件进阶指南(四)
若城
1047次阅读
2025-03-07 22:07:57
Oracle RAC ASM 磁盘组满了,无法扩容怎么在线处理?
Lucifer三思而后行
805次阅读
2025-03-17 11:33:53
Oracle 统计信息锁定解决办法
JiekeXu
557次阅读
2025-03-11 14:26:05
MySQL8.0统计信息总结
闫建(Rock Yan)
502次阅读
2025-03-17 16:04:03
2月“墨力原创作者计划”获奖名单公布
墨天轮编辑部
471次阅读
2025-03-13 14:38:19