C 动态数组

1、功能介绍
1.1、初始化动态数组
动态数组主要维护:这个这个结构体
typedef struct dynamicArry
{
void** pAddr; // 数组指针
int m_size; // 数组元素个数
int m_capacity; // 数组容量大小

}dynamicArry;

1、开辟这个结构体大小空间
2、通过传入的容量大小,对pAddr进行空间开辟
3、对容量进行初始化,元素个数默认是0
dynamicArry* array = (dynamicArry*)malloc(sizeof(dynamicArry));
if(array==NULL)
{
printf(“开辟空间失败\n”);
return NULL;
}
array->pAddr = (void**)malloc(sizeof(void*)*capacity);
array->m_size = 0;
array->m_capacity = capacity;

1.2、向动态数组中插入元素
需要参数:数组地址,插入位置,需要插入的数据
注意:
1、插入的下标文字不合理,将其改插尾部
2、判断元素个数和容量要是一样,需要扩容,将原有数组拷贝到新空间,然后释放原空间
3、需要将插入下标和以后的元素向后移动(包括插入下标)
4、移动完数据后,将元素插入,元素个数需要加1
// 无效位置尾插
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** newAddr = (void**)malloc(sizeof(dynamicArry)*newCapacity);
if(newAddr==NULL)
return;
// 3、将原空间数据拷贝到新空间
memcpy(newAddr, array->pAddr, sizeof(dynamicArry)*array->m_capacity);
// 4、释放原来的空间
free(array->pAddr);
// 5、更新空间
array->pAddr = newAddr;
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 += 1;

1.3、通过下标删除元素
删除元素,实则就是将后面的数据向前移动,然后将元素个数减1
for(int i=pos;i<array->m_size-1;i++)
{
array->pAddr[i] = array->pAddr[i+1];
}
array->m_size–;

1.4、通过元素值删除元素
函数设定需要三个形参:
数组地址,需要删除的元素地址,删除规则(函数指针)(因为可能是复合类型,本文例子就是结构体类型)

// 测试使用 数组元素类型
typedef struct Person
{
char m_name[64];
int age;
}Person;

// 回调函数类型
int myComparePerson(void* data1,void* data2)
{
Person* p1 = data1;
Person* p2 = data2;

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

循环,通过回调函数,判断是否相等,要是相等调用通过下标删除函数将其删除
for(int i=0;i<array->m_size;i++)
{
if(myComparePerson(array->pAddr,data))
{
// 如果找到要删除的数据,i就是删除的具体位置
remove_DynamicArray(array,i);
}
}

1.5、遍历数组
函数设定:需要两个形参
数组地址 回调函数地址(返回值void,参数void*,因为不确定数组内部打印的数组类型)
// 回调函数
void myPrintPerson(void* data)
{
Person* temp = (Person*)data;
printf(“姓名:%s 年龄:%d\n”,temp->m_name,temp->age);
}

// 通过回调函数打印数据
for(int i=0;i<arry->m_size;i++)
{
myprint(arry->pAddr[i]);
}

1.6、销毁动态数组
将结构体内部数据也需要释放
// 销毁
void destroy_DynamicArray(dynamicArry* array)
{
if(array==NULL)
return;
if(array->pAddr!=NULL)
{
free(array->pAddr);
array->pAddr = NULL;
}
free(array);
array=NULL;
}

2、实现
2.1、main.c文件
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include “dynamicArray.h”

int main()
{

dynamicArry* array = init_DynamicArry(3);
Person p1 = {“诸葛亮”,13};
Person p2 = {“马超”,33};
Person p3 = {“刘备”,43};
Person p4 = {“孙权”,343};
insert_DynamicArray(array,0,&p1);
insert_DynamicArray(array,1,&p2);
insert_DynamicArray(array,2,&p3);
insert_DynamicArray(array,3,&p4);

Person p5 = {“诸葛亮”,13};
remove_DynamicArray_value(array, &p5, myComparePerson);
// 删除
// remove_DynamicArray(array, 0);
// 循环
foreach_dynamicArray(array,myPrintPerson);
printf(“容量:%d 元素:%d\n”,array->m_capacity,array->m_size);
destroy_DynamicArray(array);
return 0;
}

2.2、”dynamicArray.h”文件
#ifndef dynamicArray_h
#define dynamicArray_h
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct dynamicArry
{
void** pAddr; // 数组指针
int m_size; // 数组元素个数
int m_capacity; // 数组容量大小

}dynamicArry;

// 测试使用
typedef struct Person
{
char m_name[64];
int age;
}Person;

// 销毁
void destroy_DynamicArray(dynamicArry* array);

// 通过值删除数据
void remove_DynamicArray_value(dynamicArry* array,void* data,int(*myCompare)(void*,void*));

int myComparePerson(void* data1,void* data2);

// 通过下标删除数据
void remove_DynamicArray(dynamicArry* array,int pos);

// 通过回调函数打印数据
void myPrintPerson(void* data);

// 遍历数据
void foreach_dynamicArray(dynamicArry* arry,void(*myprint)(void*));

/* 插入数组
array 数组地址
pos 插入位置
data 插入数据
*/
void insert_DynamicArray(dynamicArry* array,int pos,void* data);

// 初始化动态数组
dynamicArry* init_DynamicArry(int capacity);

#endif /* dynamicArray_h */

2.3、”dynamicArray.c”文件
#include “dynamicArray.h”

// 初始化动态数组
dynamicArry* init_DynamicArry(int capacity)
{
if(capacity<=0)
return NULL;

dynamicArry* array = (dynamicArry*)malloc(sizeof(dynamicArry));
if(array==NULL)
{
printf(“开辟空间失败\n”);
return NULL;
}
array->pAddr = (void**)malloc(sizeof(void*)*capacity);
array->m_size = 0;
array->m_capacity = capacity;

return array;
}

/* 插入数组
array 数组地址
pos 插入位置
data 插入数据
*/
void insert_DynamicArray(dynamicArry* array,int pos,void* data)
{
if(array == NULL||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** newAddr = (void**)malloc(sizeof(dynamicArry)*newCapacity);
if(newAddr==NULL)
return;
// 3、将原空间数据拷贝到新空间
memcpy(newAddr, array->pAddr, sizeof(dynamicArry)*array->m_capacity);
// 4、释放原来的空间
free(array->pAddr);
// 5、更新空间
array->pAddr = newAddr;
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 += 1;
}

// 遍历数据
void foreach_dynamicArray(dynamicArry* arry,void(*myprint)(void*))
{
if(arry==NULL || myprint==NULL)
return;
for(int i=0;i<arry->m_size;i++)
{
myprint(arry->pAddr[i]);
}
}

// 通过回调函数打印数据
void myPrintPerson(void* data)
{
Person* temp = (Person*)data;
printf(“姓名:%s 年龄:%d\n”,temp->m_name,temp->age);
}

// 打印整数
//void myprintInt(void* data)
//{
// printf(“%d\n”,data);
//}

// 通过下标删除数据
void remove_DynamicArray(dynamicArry* array,int pos)
{
if(array == NULL)
return;
if(pos<0||pos>array->m_size-1)
return;

// 数据前移
for(int i=pos;i<array->m_size-1;i++)
{
array->pAddr[i] = array->pAddr[i+1];
}
array->m_size–;
}

int myComparePerson(void* data1,void* data2)
{
Person* p1 = data1;
Person* p2 = data2;

return strcmp(p1->m_name,p2->m_name)==0 && p1->age==p2->age;
}
// 通过值删除数据
void remove_DynamicArray_value(dynamicArry* array,void* data,int(*myCompare)(void*,void*))
{
if(array == NULL || data == NULL)
return;
for(int i=0;i<array->m_size;i++)
{
if(myComparePerson(array->pAddr,data))
{
// 如果找到要删除的数据,i就是删除的具体位置
remove_DynamicArray(array,i);
}
}
}

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