通用动态数组

通用动态数组学习笔记

通用动态数组,这儿是我的笔记,希望大家可以友好交流!!谢谢#__#

今天开始学习动态数组的设计,有了前面的经验还算比较快的,也借鉴了CSDN的大神的想法!(想哭,感觉后面更加艰难,非科班自学很痛苦,还是好好务实打基础吧)。
struct darray
{
    void** data;//整个数据域的首地址
    int Capacity;//动态数组的现有容量
    int NowLen;//数组的有效长度,正常情况NowLen<Capacity
    OPERATE Compare;//函数指针变量
    OPERATE Printf;
};
首先给出动态数组的定义,再设计结构的时候,我们无需关心用户的数据是怎么样的,只需要管我们做的事。

所以我们用void*指针来保存待存储数据的地址,而我们其实更加在乎的是存储地址的一整片区域的首地址,这样我们可以在后面通过(假设A是链表)
A->data[i]来标记某个数据的指针。

一般的我们初始化的时候,会优先给数组分配一定的空间,通过
da->data = (void **)malloc(sizeof(void*)*INIT_LENGTH)来分配,INIT_LENGTH是自定义的宏,可以是5,10等等。

每次插入数据的时候,通过判断A->NewLen == A->Capacity决定是否需要对数组进行扩展,扩展的逻辑如下:
if((da->data = (void **)realloc(da->data,sizeof(void*)*Toexpand)) != NULL)
    {
        for(i = da->Capacity;i < Toexpand; i++)
        {
            da->data[i] = NULL;
        }
        da->Capacity = Toexpand;
        return true;
    }
删除的时候我们也要注意,记住之前讲过的,在哪层malloc的就应该在哪里free,所以数据从结构层我们只管A(前面说A是struct darray的指针

)的释放和data的释放,对于A->data的释放,我们在删除一个或几个数据不做处理,只在删除所有数据时,在释放A前删除A->data即可。

对于自定义的类型用户一般都会自定义一个打印的函数供回调,所以我们在动态数组中加入了函数指针,还有倘若用户自定义的数据也是需要动态分配的话,就还要自定义一个释放函数供回调,所以有A->my_free指针;

大概的思路就是这样,然后我把实现代码记录在这里:

这个是.h文件
#ifndef _DONGTAISHUZU_H_
#define _DONGTAISHUZU_H_
#include<stdlib.h>
#include<memory.h>

#define INIT_LENGTH 3
typedef (*OPERATE)();

typedef enum
{
    false = 0,
    true,
}bool;

/**动态数组的声明,定义在.c中*/
struct darray;
typedef struct darray Darray;
typedef struct darray* Darray_T;

/**接口*/
Darray_T Darray_Init(Darray_T DA);
bool  Darray_Expand(Darray_T DA);
bool Darray_PushBack(Darray_T DA,void* data);
/**在指定位置插入*/
bool Darray_InsertByIndex(Darray_T DA,int index,void* data);
/**删除指定位置的元素*/
bool Darray_DeleteByIndex(Darray_T DA,int index,OPERATE op,void ** data);

int Darray_Length(Darray_T DA);
int Darray_Capacity(Darray_T DA);

#endif
接着是实现接口
#include "dongtaishuzu.h"

/**********这么设计真的好像和用户去区无关了
为了适应更多的数据类型,我们存储的只是数据的的地址(void *)
其实我们更关注的是数据存储的那块首地址,因此我们使用
void ** 来存储数据存储区域的首地址;
********************************/
struct darray
{
    void** data;
    int Capacity;
    int NowLen;
    OPERATE Compare;
    OPERATE Printf;
};

Darray_T Darray_Init(Darray_T DA)
{
    Darray_T da = DA;
    int i= 0;
    if((da = (Darray_T)malloc(sizeof(Darray))) == NULL) return NULL;
    if((da->data = (void **)malloc(sizeof(void*)*INIT_LENGTH)) != NULL)
    {
        da->Capacity = INIT_LENGTH;
        da->NowLen = 0;
        da->Compare = NULL;
        da->Printf =NULL;
        for(i=0;i<INIT_LENGTH;i++)
        {
            da->data[i] = NULL;
        }
        return da;
    }
    return NULL;

}

bool Darray_PushBack(Darray_T DA,void* data)//相当于追加
{
    Darray_T da = DA;
    if(da == NULL || data == NULL) return false;
    if(da->NowLen == da->Capacity)
    {
        if(Darray_Expand(da))
        {
           da->data[da->NowLen] = data;
            da->NowLen++;
            return true;
        }
        else return false;
    }
    /*****没有超过容量时*****/
    da->data[da->NowLen] = data;
    da->NowLen++;
    return true;
}
bool Darray_InsertByIndex(Darray_T DA,int index,void* data)
{
    Darray_T da = DA;
    int i = 0;
    if(da == NULL) return false;
    if(da->NowLen == da->Capacity)
    {
        if(Darray_Expand(da))
        {
            for(i = da->NowLen;i > index;i--)
            {
                da->data[i] = da->data[i-1];
            }
            da->data[index] = data;
            da->NowLen++;
            return true;
        }
        return false;
    }
    for(i = da->NowLen;i > index;i--)
    {
        da->data[i] = da->data[i-1];
    }
        da->data[index] = data;
        da->NowLen++;
        return true;
}

bool  Darray_Expand(Darray_T DA)
{
    Darray_T da = DA;
    int Toexpand = DA->Capacity + INIT_LENGTH,i=0;
    if((da->data = (void **)realloc(da->data,sizeof(void*)*Toexpand)) != NULL)
    {
        for(i = da->Capacity;i < Toexpand; i++)
        {
            da->data[i] = NULL;
        }
        da->Capacity = Toexpand;
        return true;
    }
    return false;
}
/**删除元素后将数据返回供用户处理*/
bool Darray_DeleteByIndex(Darray_T DA,int index,OPERATE op,void ** data)
{
    int i = 0;
    Darray_T da = DA;
    if(da == NULL) return false;
    if(index > da->NowLen) return false;
    *data = da->data[index];
    for(i = index; i < da->NowLen; i++)
    {
        da->data[i] = da->data[i+1];

    }
    if(op!=NULL) op(*data);
     da->NowLen--;
    return true;
}
/**为每个元素执行op操作*/
void Darray_Foreach(Darray_T DA,OPERATE op,void* sxw)
{
    Darray_T da = DA;
    int i = 0;
    for(i = 0; i < da->NowLen; i++)
    {
        op(da->data[i],sxw);
    }
}
/**销毁整个数组*/
bool Darray_DeleteAll(Darray_T DA,OPERATE op,void** data)
{
    Darray_T da = DA;
    int i = 0;
    if(da == NULL) return false;
    while(Darray_Length(da)!=0)
    {
        Darray_DeleteByIndex(da,Darray_Length(da),op,data);
    }
    Darray_DeleteByIndex(da,Darray_Length(da),op,data);
    free(da->data);
    free(da);
    return true;

}

int Darray_Length(Darray_T DA)
{
    return DA->NowLen;
}

int Darray_Capacity(Darray_T DA)
{
    return DA->Capacity;
}

后来做了几个实验,把int,string,还有结构体等类型都试了一遍,都没有问题,至此应该完成了动态数组的实现,当然数组肯定离不开排序,所以我这里不一一列举我的实验,只将存整数的实验记下来,下次学的快的话,把排序弄上来,恰好和整数结合起来(嘿嘿)。

这里是主函数,运行时test_ForInt()即可,其他可以相应头文件删除即可。
#include "dongtaishuzu.h"
#include<stdio.h>
#include<stdlib.h>
#include "vector_forStructInt.h"
#include "vector_forstr.h"
#include "vector_forint.h"
#include "vector_forStructStr.h"
int main()
{
    test_StructInt();
    test_StructStr();
    test_ForStr();
    test_ForInt();
    return 0;
}
vector_forint.h
#ifndef _VECTOR_FORINT_H_
#define _VECTOR_FORINT_H_
#include <stdlib.h>
#include "dongtaishuzu.h"

void test_ForInt();
void my_IntPrintf(int *d);
#endif 
vector_forint.c
#include"vector_forint.h"

void test_ForInt()
{
    #define N 7
    int sco[N] = {10,9,6,8,7,3,4};
    int a = 99;
    void *data = NULL;
    int i = 0;
    Darray_T darray = Darray_Init(darray);
     
    printf("第四次实验这是测试存放放非动态分配的整数\n");
    for(i=0;i<N;i++)
    {
        if(Darray_PushBack(darray,&sco[i]))
        {
            printf("%d\n",i);
        }
    }

     printf("\n现在的容量是%d\n",Darray_Capacity(darray));
     printf("\n现在的长度是%d\n",Darray_Length(darray));
     printf("\n现在数组的内容是\n");
     Darray_Foreach(darray,my_IntPrintf,NULL);

    printf("\n从第2个位置插入后\n");
    Darray_InsertByIndex(darray,2,&a);
    Darray_Foreach(darray,my_IntPrintf,NULL);

    printf("\n从第2个位置删除后\n");
    Darray_DeleteByIndex(darray,2,NULL,(void **)&data);
    printf("\n%d\n",*((int*)data));
    Darray_Foreach(darray,my_IntPrintf,NULL);

    printf("\n彻底清楚后\n");
    Darray_DeleteAll(darray,NULL,(void **)&data);
    Darray_Foreach(darray,my_IntPrintf,NULL);
}
void my_IntPrintf(int *d)
{
    printf("元素%d\t",*d);
}

到这就没了,其他的就不粘贴了,哈哈哈

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值