实现C动态数组

1,220 阅读3分钟

最近在学习C,尝试着实现一下动态数组。 主要包含数组的6个基本功能:

  • 初始化
  • 插入
  • 增加
  • 修改
  • 查询
  • 删除元素

在初始化之前,首先我们需要定义一个数组的结构体 dynamic_array

数组最基本的三个元素

  1. 容量int m_capacity,
  2. 实际长度int m_size,
  3. 内容(由于数组可以放任何类型的元素进去,所以基本的元素是(void *)类型,然后我们的数组里面包含多个元素,我们把他放到一个地址里面)
void *void *void *void *void *

比如我们的元素个数是5个,我们用一个地址保存这五个元素的地址,因此我们还需要一个元素void **pAddr

struct dynamic_array{

    void** pAddr;

    int m_capacity;

    int m_size;

};

1. 初始化

初始化数组的时候,我们需要给一个默认的最大容量,也就是m_capacity,我们的返回值就是我们的结构体数组,所以我们的方法定义为:

struct dynamic_array * init_array(int capacity){

    if(capacity <= 0){
        return NULL;
    }

    return NULL;

};

接着我们需要开辟需要的内存,设置默认值

struct dynamic_array * init_array(int capacity){

    if(capacity <= 0){

        return NULL;

    }

    struct dynamic_array *array = malloc(sizeof(struct dynamic_array));

    if(array == NULL){
        return NULL;
    }
    
    void **pAddr = malloc(sizeof(void *) * capacity);

    if(pAddr == NULL){
        return NULL;
    }

    array->pAddr = pAddr;

    array->m_capacity = capacity;

    array->m_size = 0;

    return array;

};

2.插入操作

我们根据给定的数组,在指定位置插入数据 插入数据之前,需要做简单的判断

void insert_array(struct dynamic_array *array, int pos){

    if(array == NULL){
        return;
    }

    if(pos < 0 || pos > array->m_size){
        return;
    }

}

如果当前的m_size和做最大容量一样大的时候,就需要考虑扩容了

if(array->m_size == array->m_capacity){

        int new_capacity = array->m_capacity * 2;

        //开辟新的空间
        void **new_pAddr = malloc(sizeof(void *) * new_capacity);
        //把原有的数据拷贝到新的地址
        memcpy(new_pAddr, array->pAddr, sizeof(void *) * array->m_capacity);
        //释放原有的地址
        free(array->pAddr);
        //修改容量和新的数组地址
        array->m_capacity = new_capacity;

        array->pAddr = new_pAddr;

}
    
array->m_size += 1;

不管有没有扩容,新的数据插入数组,插入的位置之后的数据的值都往后移一位,插入的data直接给到指定的位置

for(int i = array->m_size - 1;i > pos;i--){

   array->pAddr[i+1] = array->pAddr[i];

}

array->pAddr[pos] = data;

完整的插入代码如下:

void insert_array(struct dynamic_array *array, int pos, void *data){

    if(array == NULL){
        return;
    }

    if(data == NULL){
        return;
    }

    if(pos < 0 || pos > array->m_size){
        return;
    }

    if(array->m_size == array->m_capacity){

        int new_capacity = array->m_capacity * 2;

        void **new_pAddr = malloc(sizeof(void *) * new_capacity);

        memcpy(new_pAddr, array->pAddr, sizeof(void *) * array->m_capacity);

        free(array->pAddr);

        array->m_capacity = new_capacity;

        array->pAddr = new_pAddr;

    }

    array->m_size += 1;

    for(int i = array->m_size - 1;i > pos;i--){

        array->pAddr[i+1] = array->pAddr[i];

    }

    array->pAddr[pos] = data;

}

3.新增元素

这个就比较简单了,直接插入到数据尾部就可以

void add_array(struct dynamic_array *array, void *data){

    if(array == NULL){
        return;
    }

    if(data == NULL){
        return;
    }

    insert_array(array, array->m_size, data);

}

4.修改元素

直接在指定位置替换就可以了

void update_array(struct dynamic_array *array, int pos, void *data){

    if(array == NULL){
        return;
    }

    if(data == NULL){
        return;
    }

    if(pos < 0 || pos >= array->m_size){
        return;
    }

    array->pAddr[pos] = data;

}

5.删除元素

删除元素比较特殊一点,如果指定位置删除了,后面的元素需要往前补,同样的m_size也需要-1. 代码如下:

void delete_array(struct dynamic_array *array, int pos){

    if(array == NULL){
        return;
    }

    if(pos < 0 || pos >= array->m_size){
        return;
    }

    if(pos == array->m_size - 1){
        //如果删除的是最后一个元素需要防止越界
        array->pAddr[pos] = NULL;
    }else{
        for(int i=pos;i< array->m_size - 1;i++){
            //把元素的值给到前面的位置
            array->pAddr[i] = array->pAddr[i+1];
        }
    }

    //更新数组长度
    array->m_size -= 1;

}

6.查询元素

我们根据指定位置,查询到具体的值,代码如下:

void * search_array(struct dynamic_array *array, int pos){

    if(array == NULL){
        return NULL;
    }

    if(pos < 0 || pos >= array->m_size){
        return NULL;
    }
    
    return array->pAddr[pos];

}

到这里我们已经实现了一个数组的基本的增删改查功能,接下来我们测试一下

//初始化数组

    struct dynamic_array *array = init_array(2);

    //新增元素
    add_array(array, (void *)1);
    add_array(array, (void *)10);
    add_array(array, (void *)100);
    
   // 通过打印我们能看到数组有三个元素,1,10,100
   //我们修改一下下标为1的元素
   update_array(array, 1, (void *)200);
   // 通过打印我们能看到数组有三个元素,1,200,100
   
   //我们删除末尾两个元素,只剩下第一个元素了
   delete_array(array, 1);
   delete_array(array, 1);
   
   //这里是直接强转的,不建议这么做
   int num = (int)array->pAddr[0];
   

通过检测,发现基本功能都是正常的,整体的思路是没问题的。