最近在学习C,尝试着实现一下动态数组。 主要包含数组的6个基本功能:
- 初始化
- 插入
- 增加
- 修改
- 查询
- 删除元素
在初始化之前,首先我们需要定义一个数组的结构体 dynamic_array
数组最基本的三个元素
- 容量int m_capacity,
- 实际长度int m_size,
- 内容(由于数组可以放任何类型的元素进去,所以基本的元素是(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];
通过检测,发现基本功能都是正常的,整体的思路是没问题的。