动态数组(dynamic array),顾名思义就是能改变大小的数组。使用动态数组可以有效的提高内存利用率。
下面附上动态数组的C语言实现
头文件:dynamic_array.h
#ifndef __DYNAMIC_ARRAY_H__
#define __DYNAMIC_ARRAY_H__
#ifdef __cpluscplus
extern "C" {
#endif
//动态数组结构体
struct dynamic_array
{
void **pAddr; //维护在堆区真实的数组指针
int m_capacity; //数组容量
int m_size; //数组大小
};
//初始化数组
struct dynamic_array * init_dynamic_array(int capacity);
//插入功能
void insert_dynamic_array(struct dynamic_array *array,int pos,void *data);
//遍历数组
void foreach_dynamic_array(struct dynamic_array *array,void(*my_foreach)(void *));
//删除功能
//按照位置来删除
void remove_pos_dynamic_array(struct dynamic_array *array,int pos);
//按照数值来删除
void remove_value_dynamic_array(struct dynamic_array *array,void *data,int(*my_compare)(void *,void *));
//销毁数组
void destroy_dynamic_array(struct dynamic_array *array);
#ifdef __cplusplus
}
#endif
#endif
动态数组功能实现: dynamic_array.c
#include "dynamic_array.h"
//初始化数组
struct dynamic_array * init_dynamic_array(int capacity)
{
//判断数据的有效性
if(capacity <= 0)
{
return NULL;
}
struct dynamic_array * array = malloc(sizeof(struct dynamic_array));
//判断内存是否申请成功
if(NULL == array)
{
return NULL;
}
//设置容量
array->m_capacity = capacity;
//设置大小
array->m_size = 0;
//维护在堆区的数组指针
array->pAddr = malloc(sizeof(void *)*array->m_capacity);
}
//插入功能
void insert_dynamic_array(struct dynamic_array *array,int pos,void *data)
{
if(NULL == array)
{
return NULL;
}
if(NULL == data)
{
return NULL;
}
if(pos < 0 || pos > array->m_size)
{
//无效的位置 进行尾插(也可以return)
pos = array->m_size;
}
//先判断是否已经满载,如果满了,动态开辟
if(array->m_size >= array->m_capacity)
{
//1.申请一个更大的空间
int new_capacity = array->m_capacity * 2;
//2.创建新空间
void ** new_space = malloc(sizeof(void *)*new_capacity);
//3.将原有的数据拷贝到新空间下
memcpy(new_space,array->pAddr,sizeof(void *)*array->m_capacity);
//4.释放原有的空间
free(array->pAddr);
//5.更新指针指向
array->pAddr = new_space;
//6.更新容量大小
array->m_capacity = new_capacity;
}
//插入新的数据元素
//从最后一个位置开始,依次移动数据(后移)
for(int i = array->m_size;i >= pos;i--)
{
array->pAddr[i + 1] = array->pAddr[i];
}
//将新数据查到指定位置
array->pAddr[pos] = data;
//更新大小
array->m_size++;
}
//遍历数组
void foreach_dynamic_array(struct dynamic_array *array,void(*my_foreach)(void *))
{
//数据有效性判断
if(NULL == array)
{
return NULL;
}
if(NULL == my_foreach)
{
return NULL;
}
for(int i = 0;i < array->m_size;i++)
{
my_foreach(array->pAddr[i]);
}
}
//删除功能
//按照位置来删除
void remove_pos_dynamic_array(struct dynamic_array *array,int pos)
{
//数据有效性判断
if(NULL == array)
{
return NULL;
}
if(pos < 0 || pos > array->m_size -1)
{
//无效的位置 直接return
return NULL;
}
//从pos位置开始 到数组尾 数据进行前移
for(int i = pos;i < array->m_size - 1;i++)
{
array->pAddr[i] = array->pAddr[i + 1];
}
array->m_size--;
}
//按照数值来删除
void remove_value_dynamic_array(struct dynamic_array *array,void *data,int(*my_compare)(void *,void *))
{
//数据有效性判断
if(NULL == array)
{
return NULL;
}
if(NULL == data)
{
return NULL;
}
for(int i = 0;i < array->m_size;i++)
{
if(my_compare(array->pAddr[i],data))
{
remove_pos_dynamic_array(array,i);
break;
}
}
}
//销毁数组
void destroy_dynamic_array(struct dynamic_array *array)
{
if(NULL == array)
{
return NULL;
}
if(NULL != array->pAddr)
{
free(array->pAddr);
array->pAddr = NULL;
}
free(array);
array = NULL;
}
功能写好了,那就要测试一下,新建了test.c和test.h文件。
测试头文件:test.h
#ifndef __TESE_H__
#define __TESE_H__
#ifdef __cpluscplus
extern "C" {
#endif
#define DYNAMIC_ARRAY_LEN 5
//测试结构体
struct Person
{
char name[64];
int age;
};
//打印数组
void my_print_person(void *data);
//比较数组值
int my_compare_person(void *data1,void *data2);
//动态数组功能测试
void function_test(void);
#ifdef __cplusplus
}
#endif
#endif
测试文件:test.c
#include "test.h"
void my_print_person(void *data)
{
struct Person *p = data;
printf("姓名:%s 年龄:%d\n",p->name,p->age);
}
int my_compare_person(void *data1,void *data2)
{
struct Person *p1 = data1;
struct Person *p2 = data2;
return strcmp(p1->name,p2->name) == 0 && p1->age == p2->age;
}
void function_test(void)
{
//创建动态数组
struct dynamic_array *arr = init_dynamic_array(DYNAMIC_ARRAY_LEN);
//准备出6个person数据
struct Person p1 ={"亚瑟",18};
struct Person p2 ={"张飞",20};
struct Person p3 ={"关羽",30};
struct Person p4 ={"项羽",28};
struct Person p5 ={"宫本",43};
struct Person p6 ={"妲己",19};
//打印插入前容量
printf("当前的容量:%d\n",arr->m_capacity);
//将数据插入到动态数组中
insert_dynamic_array(arr,0,&p1);
insert_dynamic_array(arr,0,&p2);
insert_dynamic_array(arr,0,&p3);
insert_dynamic_array(arr,2,&p4);
insert_dynamic_array(arr,10,&p5);
insert_dynamic_array(arr,1,&p6);
//输出顺序:关羽 妲己 张飞 项羽 亚瑟 宫本
//遍历输出插入结果
foreach_dynamic_array(arr,my_print_person);
//打印插入后容量
printf("插入数据后的容量:%d\n",arr->m_capacity);
//删除指定位置数据
remove_pos_dynamic_array(arr,1);
//遍历输出删除后的数组
printf("删除元素后,数组中的数据为:\n");
foreach_dynamic_array(arr,my_print_person);
//删除指定数据值
struct Person p ={"宫本",43};
remove_value_dynamic_array(arr,&p,my_compare_person);
printf("删除指定值后,数组中的数据为:\n");
foreach_dynamic_array(arr,my_print_person);
//销毁数组
destroy_dynamic_array(arr);
arr = NULL;
}
接下来把需要用的所有头文件放到includes.h里面,这样便于管理。
头文件集合:includes.h
#ifndef __INCLUDES_H__
#define __INCLUDES_H__
#ifdef __cpluscplus
extern "C" {
#endif
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "dynamic_array.h"
#include "test.h"
#ifdef __cplusplus
}
#endif
#endif
在主程序中调用function_test函数测试功能
入口文件:main.c
#include "includes.h"
//主函数
int main(void)
{
//功能测试
function_test();
return 0;
}