动态数组代码实现

一、动态数组


一般在静态数组定义后,系统就会为其分配对应长度的连续的专有内存空间,可是,我们都知道,不同的运行样例,所需要的数组长度是不一样的,为了所有样例都可以执行,一般我们会将数组长度设置为一个很大的值,比如:我一般都是借助宏定义直接声明1000,这个长度是可以满足我日常所需的。虽然这种方式,满足了一般运行的要求,但是它极大的浪费了内存。

于是我们引出了动态数组的概念,顾名思义,“动态”体现在数组长度可以由用户自己定义上。那么今天来总结一下,动态数组的两种实现方式。

二、动态数组设计思路

1、思路图

2、定义struct dynamicArray结构体

2.1、属性:

  • void ** pAddr 维护真实在堆区创建的数组的指针

  • int m_capacity; 数组容量

  • int m_size; 数组大小

struct dynamicArray {

    void **pAddr; //维护真实在堆区创建的数组的指针

    int m_capacity; //数组容量

    int m_size; //数组大小
};

3、 动态数组初始化

//初始化数组
struct dynamicArray *init_DynamicArray(int capacity) {
    if (capacity <= 0) {
        return NULL;
    }

    //跟数组分配空间
    struct dynamicArray *array = malloc(sizeof(struct dynamicArray));
    if (array == NULL) {

        return NULL;
    }
    //数组分配堆区
    //数组初始化
    array->pAddr = malloc(sizeof(void *) * capacity);
    array->m_capacity = capacity;
    array->m_size = 0;

    return array;
}

3、插入数组

//插入数组
void insert_DynamicArray(struct dynamicArray *array, int pos, void *data) {

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

    //无效位置 尾插
    if (pos < 0 || pos > array->m_size) {
        pos = array->m_size;
    }
    //判断数组是否满了,满了就动态扩展
    if (array->m_size == array->m_capacity) {

        //1.计算新空间大小
        int newCapacity = array->m_capacity * 2;

        //2.给每个元素申请新的堆空间
        void **newSpace = malloc(sizeof(void *) * newCapacity);

        //3.将原有的数据拷贝新空间中
        memcpy(newSpace, array->pAddr, sizeof(void *) * array->m_capacity);

        //4.释放原有的内存空间
        free(array->pAddr);

        //5.更新新空间指向
        array->pAddr = newSpace;

        //6.更新新容量
        array->m_capacity = newCapacity;

    }

    //插入新的元素
    //移动元素 进行插入新的元素
    for (int i = array->m_size - 1; i >= pos; i--) {
        //所有数据向后移动
        array->pAddr[i + 1] = array->pAddr[i];
    }

    //将新元素 插入到指定位置
    array->pAddr[pos] = data;
    //更新大小
    array->m_size++;
}

4、遍历数组

//遍历数组
void forEach_DynamicArray(struct dynamicArray *array, void(*myPrint)(void *)) {
    if (array == NULL) {

        return;
    }
    if (myPrint == NULL) {

        return;
    }
    for (int i = 0; i < array->m_size; i++) {
        myPrint(array->pAddr[i]);
    }
}

这里myPrint为用户余姚自定义的回调函数

5、删除数组

  • 按位置删除
//删除数组 按位置删除
void removeByPos_DynamicArray(struct dynamicArray *array, int pos) {

    if (array == NULL) {
        return;
    }

    //无效位置删除
    if (pos < 0 || pos > array->m_size - 1) {
        return;
    }
    //数据向前移动一位
    for (int i = 0; i < array->m_size; i++) {
        array->pAddr[i] = array->pAddr[i + 1];
    }

    //更新数组大小
    array->m_size--;
}
  • 按值删除
//删除数组 按值删除
void removeByValue_DynamicArray(struct dynamicArray *array, void *data, int (*myCompare)(void *, void *)) {

    if (array == NULL) {
        return;
    }

    if (data == NULL) {
        return;
    }
    //
    for (int i = 0; i < array->m_size; i++) {

        if (myCompare(array->pAddr[i], data)) {

            //如果找到要删除的数据,i就是要删除的位置
            removeByPos_DynamicArray(array, i);
            break;
        }
    }

myCompare为回调函数,用户自定义比较规则

6、销毁数组

//销毁数组
void destroy_DynamicArray(struct dynamicArray* array)
{
	if (array == NULL)
	{
		return;	
    }
	if (array->pAddr != NULL)
	{
		free(array->pAddr);
		array->pAddr = NULL;
	}
	free(array);
	array = NULL;
}

三、调试

1、回调函数 myPrintPerson

//回调函数
void myPrintPerson(void *data) {
    struct person *p = data;
    printf("姓名:%s,年龄:%d\n", p->name, p->age);
}

2、回调函数 myCompare

//回调函数
int myCompare(void *data1, void *data2) {

    struct person *p1 = data1;
    struct person *p2 = data2;
    p1->name;
    p2->name;

    return strcmp(p1->name, p2->name) == 0 && p1->age == p2->age;
}

3.测试

  • 定义结构体Person
struct person {
    char name[64];
    char age;
};
  • main
int main() {

    //初始化数组
    struct dynamicArray *array = init_DynamicArray(5);

    //准备数据
    struct person p1 = {"亚瑟", 18};
    struct person p2 = {"安琪拉", 12};
    struct person p3 = {"凯", 11};
    struct person p4 = {"孙悟空", 12};
    struct person p5 = {"达摩", 111};
    struct person p6 = {"牛魔", 123};

    printf("插入数据后:容量:%d 大小:%d\n", array->m_capacity, array->m_size);
    //插入数据
    insert_DynamicArray(array, 0, &p1);
    insert_DynamicArray(array, 0, &p2);
    insert_DynamicArray(array, 1, &p3);
    insert_DynamicArray(array, 0, &p4);
    insert_DynamicArray(array, -1, &p5);
    insert_DynamicArray(array, 2, &p6);

    //遍历数据
    forEach_DynamicArray(array, myPrintPerson);
    printf("插入数据后:容量:%d 大小:%d\n", array->m_capacity, array->m_size);

    //测试删除
    removeByPos_DynamicArray(array, 0);
    forEach_DynamicArray(array, myPrintPerson);
    printf("删除数据后:容量:%d 大小:%d\n", array->m_capacity, array->m_size);


    struct person p = {"达摩", 111};
    removeByValue_DynamicArray(array, &p, myCompare);
    forEach_DynamicArray(array, myPrintPerson);
    printf("删除数据后:容量:%d 大小:%d\n", array->m_capacity, array->m_size);

    return 0;
}
posted @   zggb  阅读(72)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示