29.动态数组

  • 学习人数 15K+
  • 适合有C语言基础人群学习
avatar
林耿亮

你好编程主讲老师

1. 动态数组

在实际项目中,我们经常与各式各样的数据打交道。

例如:我们处理的是学生的数据。

struct student {
    int id;         //  学号
    char name[20];  //  姓名
    int gender;     //  性别
    int mark;       //  成绩
};

学生数据使用一个结构体表示,该结构体拥有4个成员。分别为:

  • 学号
  • 姓名
  • 性别
  • 成绩

大多数情况下,数据的数量是不确定的,可能随着时间流逝而增加或减少。

例如:一开始有5个学生,后来增加到8个,再后来增加到15个。最后,减少到3个学生。

我们可以使用数组来盛放这些学生的数据,但是,声明数组时,声明一个长度为多少的数组,是一个需要考虑的问题。

如果我们能预知学生数量最多为15个,我们可以声明一个元素数量为15的结构体数组。

struct student arrStudent[15];

但是,大多数情况下,我们是不能预知数据到底有多少的。因此,最好是能够让数组的长度根据数据的多少自动增长。一种常用的数组增长策略是:当数组已经装满时,将数组长度增长到原来的两倍

例如,数组的初始长度为5,当数组需要继续添加数据时,数组的长度增长为原来的两倍,即10个元素。若数组再次被装满,将数组的长度再次增加为原来的两倍,即20个元素。

为了实现上述的特性,我们可以借助于mallocrealloc函数。

void *malloc(size_t size);
void *realloc(void *ptr, size_t new_size);

malloc函数可以向系统申请size字节大小的内存空间。若申请成功,则返回这段内存空间的首地址。

relloc函数可以用于增长或缩短之前申请的内存空间。relloc函数的第一个参数是之前申请的内存空间的首地址,它会根据第二个参数,长度new_size增长或缩短之前申请的内存空间,并返回调整长度后的内存空间的首地址。

2. 实现动态数组

下面我们来实现这个动态数组对象,我们将这个对象命名为vector

struct vector {
    bool (*append)(struct vector* pVec, struct student data);
    struct student (*get)(struct vector* pVec, int index);
    void (*clear)(struct vector *pVec);
    void (*remove)(struct vector* pVec, int index);

    struct student *pData;
    int size;
    int capacity;
};

成员

这个对象有3个成员,它们分别是:

  • struct student *pData
  • int size
  • int capacity

pData用于记录数组的首元素指针。 size为数组中盛放的数据的长度。 capacity为整个数组拥有的元素个数,即数组的容量。

初始化

我们定义一个符号常量VECTOR_INIT_CAPACITY用来表示初始情况下,数组拥有的元素个数。为了方便测试,我们把这个数值定的小一点,暂时将数值设定为1。

#define VECTOR_INIT_CAPACITY 1

定义一个vectorInit函数,用于vector对象的初始化。初始情况下,使用malloc函数申请一个元素类型为struct student的数组,数组的元素数量为VECTOR_INIT_CAPACITY。保存这个数组的首元素指针到pData中。此时,数组拥有的元素个数为VECTOR_INIT_CAPACITY,盛放的数据长度为0。

void vectorInit(struct vector* pVec)
{
    pVec->pData = (struct student*)malloc(sizeof(struct student) * VECTOR_INIT_CAPACITY);
    pVec->size = 0;
    pVec->capacity = VECTOR_INIT_CAPACITY;
}

方法

接下来我们再来看vector对象的4个方法。

bool (*append)(struct vector* pVec, struct student data);
struct student (*get)(struct vector* pVec, int index);
void (*clear)(struct vector *pVec);
void (*remove)(struct vector* pVec, int index);

append方法用于向数组中添加一个struct student数据。如果添加成功返回true,否则返回falseget方法用于从数组中获取一个struct student数据,index参数为需要获取的数组元素下标。 clear方法用于清除所有数组中盛放的数据,并将size复位为0,capacity复位为VECTOR_INIT_CAPACITYremove方法用于删除数组中下标为index的元素,并将size减1。