1-动态数组

1. 数据结构概念

  1. 算法的特性
    (1)零个或多个输入;
    (2)一个或多个输出;
    (3)有穷性,在可接受的时间内得出结果;
    (4)确定性,不会出现二义性;
    (5)可行性,执行方法可以实现的。
  2. 数据结构分类
  • 逻辑结构
    (1)集合:相互之间无关系;
    (2)线性:一对一关系:如数组、链表;
    (3)树形:一对多关系:如树;
    (4)图形:多对多关系:如图;
  • 物理结构
    (1)顺序存储:如数组;
    (2)链式存储:如链表;

2. 动态数组

2.1 动态数组原理

  1. 在堆区创建一个结构体记录数组自身信息;
    (1)结构体成员包括:数组首地址、数组容量、数组大小;
    (2)数组的元素并非用户的数据,而是用户数据的地址
    (3)由于无法确定用户的数据类型,因此数组元素类型为void*指向用户数据的地址,数组首地址为void**
//定义数组结构体
typedef struct dynamicArray 
{
	void** pAddr;	//数组首地址
	int Capacity;	//数组容量
	int m_Size;		//数组大小
}dynamicArray;
  1. 向数组中添加新元素
    (1)在堆中开辟一个更大的数组区域;
    (2)将原来的元素复制到新数组;
    (3)释放原来的数组空间。

2.2 数组的初始化

  1. 在堆中申请动态数组的空间;
  2. 初始化数组;
  3. 将数组的地址返回;
/*初始化数组*/
dynamicArray* init_dynamicArray(int capacity)
{
	if (capacity <= 0)
	{
		return NULL;
	}

	//1.申请数组内存空间
	dynamicArray* arr = malloc(sizeof(dynamicArray));
	if (NULL == arr)
	{
		return NULL;
	}
	
	//2.初始化数组
	arr->pAddr = malloc(sizeof(void*) * capacity);
	arr->Capacity = capacity;
	arr->m_Size = 0;

	return arr;
}

2.3 数组元素的插入

  1. 判断插入位置是否合法,若不符合发则进行尾插;
  2. 若当前数组已经满了
    (1)开辟新的数组空间;
    (2)将原数组元素移到新数组;
    (3)释放原数组空间;
    (4)更新数组结构体中的数组信息;
  3. 插入新的元素到数组中
    (1)将插入点的原来元素及其后的元素整体向后移动一个空间;
    (2)将新元素插入;
    (3)数组的大小增加。
/*插入数组元素*/
void insert_dynamicArray(dynamicArray* arr, void* data, int pos)
{
	if (NULL == arr)
	{
		return;
	}
	if (NULL == data)
	{
		return;
	}
	//1.判断插入位置是否合法
	if (pos <= 0 || pos > arr->m_Capacity)
	{
		//1.1不合法则进行尾插
		pos = arr->m_Size;
	}
	//2.判断数组是否已经满了
	if (arr->m_Size == arr->m_Capacity)
	{
		//2.1若已经满了,则开辟新数组区域
		int newCapacty = arr->m_Capacity * 2;
		void** newSpace = malloc(sizeof(void*) * newCapacty);
		if (NULL == newSpace)
		{
			return;
		}
		//2.2将原数组元素复制到新数组
		memcpy(newSpace, arr->pAddr, sizeof (void*) * arr->m_Capacity);
		//2.3释放原数组空间
		free(arr->pAddr);
		//2.4更新数组的信息
		arr->pAddr = newSpace;
		arr->m_Capacity = newCapacty;
	}
	//3.插入元素
		//3.1将插入地址的数据整体后移
	for (int i = arr->m_Size - 1; i >= pos; i--)
	{
		arr->pAddr[i + 1] = arr->pAddr[i];
	}
		//3.2插入元素
	arr->pAddr[pos] = data;
	arr->m_Size++;
}

2.4 数组的遍历

  1. 循环访问每个数组元素;
  2. 将每个元素回调给调用的函数;
/*遍历*/
void foreach_dynamicArray(dynamicArray* arr, void (*myPrintf)(void*))
{
	if (NULL == arr)
	{
		return;
	}
	for (int i = 0; i < arr->m_Size; i++)
	{
		myPrintf(arr->pAddr[i]);
	}
}

2.4 测试

/*回调函数*/
void myPrint(void* data)
{
	Person* person = (Person*)data;
	printf("名字:%s\t年龄:%d\n", person->name, person->age);
}
void test01()
{
	/*定义数组元素*/
	Person st1 = { "aaa", 18 };
	Person st2 = { "bbb", 19 };
	Person st3 = { "ccc", 20 };
	Person st4 = { "ddd", 21 };
	Person st5 = { "eee", 22 };
	//1.初始化数组
	dynamicArray* arr = init_dynamicArray(4);
	printf("插入前数组容量:%d\n", arr->m_Capacity);
	printf("插入前数组大小:%d\n", arr->m_Size);
	//2.插入元素    st4 st1 st2 st3 st5
	insert_dynamicArray(arr, &st1, 0);
	insert_dynamicArray(arr, &st2, 1);
	insert_dynamicArray(arr, &st3, -1);
	insert_dynamicArray(arr, &st4, 0);
	insert_dynamicArray(arr, &st5, 10);
	//3.遍历元素
	foreach_dynamicArray(arr, myPrint);
	printf("插入前数组容量:%d\n", arr->m_Capacity);
	printf("插入前数组大小:%d\n", arr->m_Size);
}

2.7 数组的删除

  1. 判断删除位置是否合法,不合法则直接返回
  2. 删除该位置上的元素
    (1)将该元素后面的元素整体左移覆盖当前元素
    (2)数组大小减小;
  3. 删除对应数值的元素
    (1)遍历整个数组,通过回调函数判断当前元素是否是要删除的元素
    (2)删除后数组大小减小
/*数组的删除*/
void deleteByPos_dynamicArray(dynamicArray* arr, int pos)
{
	if (NULL == arr)
	{
		return;
	}
	//1.判断删除位置是否合法
	if (pos < 0 || pos > arr->m_Size-1)
	{
		return;
	}
	//2.删除元素
		//2.1将删除位置后面的元素覆盖要删除的元素
	for (int i = pos; i < arr->m_Size; i++)
	{
		arr->pAddr[i] = arr->pAddr[i + 1];
	}
		//2.2数组元素减小
	arr->m_Size--;
}
void deleteByVal_dynamicArray(dynamicArray* arr, void* data, int(*cmp)(void*, void*))
{
	if (NULL == arr)
	{
		return;
	}
	//1.遍历数组元素
	for (int i = 0; i < arr->m_Size; i++)
	{
		if (cmp(arr->pAddr[i], data))
		{
			deleteByPos_dynamicArray(arr, i);
			break;
		}
	}
}

2.6 数组的销毁

  1. 释放数组的内存空间
  2. 释放数组结构体的内存空间
void destory_dynamicArray(dynamicArray* arr)
{
	if (NULL == arr)
	{
		return;
	}
	if(arr->pAddr != NULL)
	{
		free(arr->pAddr);
		pAddr = NULL;
	}
	free(arr);
	arr = NULL;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值