如果有错误或者理解不到位的地方还请各位指正!
数据结构的相关问题,可以参考笔者写的系列数据结构文章,或者加我交流!
声明:以下内容是对清华大学出版社出版,由严蔚敏和吴伟民编著的图书《数据结构》(C语言版)的代码实现。
图书PDF版本可移步公众号【李歘歘】回复电子书领取。
《数据结构》(C语言版)是各大高校计算机有关专业的指定教材,还是计算机考研的统考专业课数据结构指定的参考书籍,数据结构作为408专业课的重中之重,值得大家重视。
上次说到了队列的循环队列,今天我们来说一下有关数组的顺序数组,相关知识点可以先了解一下。
可以适当的先了解一下stdarg头文件写的三个宏:va_start、va_arg、va_end
书中位置(页码):P100 P102-P104
函数定义及说明:
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
#include
#include
//标准头文件,提供三个宏(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
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
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语言版)——队列(顺序队列)
数据结构(严蔚敏C语言版)——队列(链队列)
数据结构(严蔚敏C语言版)——栈(链栈)
数据结构(严蔚敏C语言版)——栈(顺序栈)
数据结构(严蔚敏C语言版)——线性表(静态链表)
数据结构(严蔚敏C语言版)——线性表(普通链表)
数据结构(严蔚敏C语言版)——线性表(顺序表)