数组与广义表(数组的顺序表示和实现)

此操作中需要用到的一些知识

数组的几个基址

  • 数组维界地址(int *base):指向一个一维数组B他存放了数组A个维度元素的数目
  • 数组元素基址(*bounds):以二维数组A为例,将数组拉成一个向量L组成一个线性结构的首地址
  • 数组映像函数基址(*constans):指向一个数组C,它存放了数组A各维度上的数字加1时,元素在线性结构L上移动的距离

有一个二维数组A[3][4] bouds[2] = {3,4} constans[2] = [4,1] eg:求A[2][3] 地址
= A[0][0]+2constans[0]+3constans[1]

可变参数头文件:stdarg.h

声明在stdarg.h中的va_list类型代表一种用于存储形参对应的形参列表中省略号部分的数据对象(详情可变参数)
(上面链接是自己记得笔记在幕布,复制过来看的不是很明了)

代码实现部分

头文件部分

#ifdef DEBUG是测试使用的,已经把#defineDEBUg注释掉了

初始化函数


Status InitArray(Array* A, int dim, ...)
{
    va_list ap;   //声明一个存储参数对象
    int elemtotal; //A的元素总和
    int i;
    if (dim<1 || dim>MAX)
    {
        printf("请输入合法维度\n");
        return ERROR;
    }
    A->dim = dim;
    //创建维界基址数组(保存各维长度)
    A->bounds = (int*)malloc(dim * sizeof(int));
    if (!A->bounds)
    {
        printf("分配失败\n");
        exit(0);
    }
    elemtotal = 1;
    va_start(ap, dim);  //把ap初始化为一个参数列表
    for (i = 0; i < dim; i++)
    {
        A->bounds[i] = va_arg(ap, int);
        //第一个参数变量名,第二个参数变量类型
        if (A->bounds < 0)
        {
            printf("不合法\n");
            return ERROR;
        }
        elemtotal *= A->bounds[i];
    }
#ifdef DEBUG
    printf("%d\n", elemtotal);
#endif
    va_end(ap);
    //初始化数组
    A->data = (ElemType*)malloc(elemtotal * sizeof(ElemType));
    if (!A->data)
    {
        printf("1hao内存不足\n");
        exit(0);
    }
    A->constants = (int*)malloc(dim * sizeof(int));
    if (!A->constants)
    {
        printf("内存不足\n");
        exit(0);
    }
    A->constants[dim - 1] = 1;
    for (i = dim - 2; i >= 0; i--)
        A->constants[i] = A->constants[i + 1] * A->bounds[i + 1];
    
#ifdef DEBUG
    PrintData(A->constants);
#endif // DEBUG

    printf("成功\n");

    return OK;
}

销毁函数

将各个数组地址全部释放,将数组维度初始化为0

Status DestroyArray(Array* A)
{
    if (!A->data)
        return ERROR;
    free(A->data);
    A->data = NULL;
    if (!A->bounds)
        return ERROR;
    free(A->bounds);
    A->bounds = NULL;
    if (!A->constants)
        return ERROR;
    free(A->constants);
    A->constants = NULL;
    A->dim = 0;

    return OK;
}

查询位置函数

查询可变参数中的位置是数组中的第几个元素

Status Locate(Array* A, va_list ap, int* off)
{
    int i, ind;
    *off = 0;
    for (i = 0; i < A->dim; i++)
    {
        ind = va_arg(ap, int);
#ifdef DEBUG
        printf("ind是%d\n", ind);
#endif // DEBUG
        if (ind<0 || ind>A->bounds[i])
        {
            printf("%d维数组已满\n",i + 1);
            return ERROR;
        }
        *off += ind * A->constants[i];
    }
#ifdef DEBUG
    printf("*off是%d\n", *off);
#endif

    return OK;
}

将e赋值为A所指定的元素值

Status Value(Array* A, ElemType* e, ...)
{
    //A是n维数组,e是元素变量
    //若下标合法则将e赋值为A所指定的元素值
    va_list ap;
    int off;
    Status result;
    va_start(ap, *e);

    result = Locate(A, ap, &off);
    if (result <= 0)
        return result;
    *e = *(A->data + off);

    return OK;
}

插入元素

查找传入的位置是数组中的那个位置,将此位置赋值为e

Status Assign(Array* A, ElemType e, ...)
{
    va_list ap;
    int off;
    Status result;
    va_start(ap, e);

    result = Locate(A, ap, &off);
    if (result <= 0)
        return result;
    *(A->data + off) = e;

    return OK;
}

打印函数

先用*bounds算出数组总公共有多少个元素,在开始遍历

void ArrPrint(Array A)
{
    int j, i;
    for (i = 0, j = 1; i < A.dim; i++)
        j *= A.bounds[i];
#ifdef DEBUG
    printf("打印函数%d\n", j);
#endif
    printf("开始遍历\n");
    for (i = 0; i < j; i++)
        printf("%d ", A.data[i]);
}

完整头文件

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

#define MAX 8
#define OK 1
#define ERROR 0
#define DEBUG

typedef int Status;
typedef int ElemType;

typedef struct {
    ElemType* data; //数组元素基址
    int dim;        //数组维数
    int* bounds;    //数组维界基址
    int* constants; //数组映像函数基址
}Array;

void PrintData(int* data);

Status InitArray(Array* A, int dim, ...)
{
    va_list ap;   //声明一个存储参数对象
    int elemtotal; //A的元素总和
    int i;
    if (dim<1 || dim>MAX)
    {
        printf("请输入合法维度\n");
        return ERROR;
    }
    A->dim = dim;
    //创建维界基址数组(保存各维长度)
    A->bounds = (int*)malloc(dim * sizeof(int));
    if (!A->bounds)
    {
        printf("分配失败\n");
        exit(0);
    }
    elemtotal = 1;
    va_start(ap, dim);  //把ap初始化为一个参数列表
    for (i = 0; i < dim; i++)
    {
        A->bounds[i] = va_arg(ap, int);
        //第一个参数变量名,第二个参数变量类型
        if (A->bounds < 0)
        {
            printf("不合法\n");
            return ERROR;
        }
        elemtotal *= A->bounds[i];
    }
#ifdef DEBUG
    printf("%d\n", elemtotal);
#endif
    va_end(ap);
    //初始化数组
    A->data = (ElemType*)malloc(elemtotal * sizeof(ElemType));
    if (!A->data)
    {
        printf("1hao内存不足\n");
        exit(0);
    }
    A->constants = (int*)malloc(dim * sizeof(int));
    if (!A->constants)
    {
        printf("内存不足\n");
        exit(0);
    }
    A->constants[dim - 1] = 1;
    for (i = dim - 2; i >= 0; i--)
        A->constants[i] = A->constants[i + 1] * A->bounds[i + 1];
    
#ifdef DEBUG
    PrintData(A->constants);
#endif // DEBUG

    printf("成功\n");

    return OK;
}

Status DestroyArray(Array* A)
{
    if (!A->data)
        return ERROR;
    free(A->data);
    A->data = NULL;
    if (!A->bounds)
        return ERROR;
    free(A->bounds);
    A->bounds = NULL;
    if (!A->constants)
        return ERROR;
    free(A->constants);
    A->constants = NULL;
    A->dim = 0;

    return OK;
}


Status Locate(Array* A, va_list ap, int* off)
{
    int i, ind;
    *off = 0;
    for (i = 0; i < A->dim; i++)
    {
        ind = va_arg(ap, int);
#ifdef DEBUG
        printf("ind是%d\n", ind);
#endif // DEBUG
        if (ind<0 || ind>A->bounds[i])
        {
            printf("%d维数组已满\n",i + 1);
            return ERROR;
        }
        *off += ind * A->constants[i];
    }
#ifdef DEBUG
    printf("*off是%d\n", *off);
#endif

    return OK;
}

Status Value(Array* A, ElemType* e, ...)
{
    //A是n维数组,e是元素变量
    //若下标合法则将e赋值为A所指定的元素值
    va_list ap;
    int off;
    Status result;
    va_start(ap, *e);

    result = Locate(A, ap, &off);
    if (result <= 0)
        return result;
    *e = *(A->data + off);

    return OK;
}

Status Assign(Array* A, ElemType e, ...)
{
    va_list ap;
    int off;
    Status result;
    va_start(ap, e);

    result = Locate(A, ap, &off);
    if (result <= 0)
        return result;
    *(A->data + off) = e;

    return OK;
}

void ArrPrint(Array A)
{
    int j, i;
    for (i = 0, j = 1; i < A.dim; i++)
        j *= A.bounds[i];
#ifdef DEBUG
    printf("打印函数%d\n", j);
#endif
    printf("开始遍历\n");
    for (i = 0; i < j; i++)
        printf("%d ", A.data[i]);
}

void PrintData(int* data)
{
    int j;
    int i = sizeof(data) / sizeof(data[0]);
    for (j = 0; j < i; j++)
        printf("%d ", data[j]);
}

主函数测试部分

中间有一对中括号作用是防止变量重复,第二对i,j,e只在中括号中起作用

#define _CRT_SECURE_NO_WARNINGS 1

#include "Array.h"

int main()
{
	Array A;

	printf("测试InitArray函数\n");
	printf("声明一个三行五列的二维数组\n");
	InitArray(&A, 2, 3, 5);

	printf("测试Assign函数\n");
	printf("将e插入第i行第j列的二维数组中\n");
	int i, j;
	ElemType e;
	for (i = 0; i < A.bounds[0]; i++)
	{
		for (j = 0; j < A.bounds[1]; j++)
		{
			printf("请输入要插入的值\n");
			scanf("%d", &e);
			Assign(&A, e, i, j);
		}
	}
	ArrPrint(A);

	printf("测试Value函数\n");
	{
		printf("将数组中第i行第j列的元素赋值给m\n");
		int i, j;
		ElemType e;
		printf("请输入要获取第i行第j列的元素:");
		scanf("%d %d", &i, &j);
		Value(&A, &e, i, j);
		printf("赋值后m为%d\n", e);
	}

	printf("测试DestroyArray函数\n");
	printf("销毁前数组地址是%p 维度是%d\n", A.data,A.dim);
	DestroyArray(&A);
	printf("销毁后%p 维度是%d\n", A.data,A.dim);

	return 0;
}

留下你的大赞嘿嘿!!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值