1.动态数组

1.动态数组结构

  上图所示,该动态数组有3个元素,空间容量是6,每个元素类型为void*,因为void*可以接受任何类型指针,可以用来存各种类型指针。第一个元素地址为pAddr,第一个元素为*pAddr。

用结构体表示动态数组为:

//动态数组结构体
struct dynamicArray
{
	void** pAddr;//维护真实在堆区的数组的指针
	int m_capacity;//数组容量
	int m_size;//数组大小
};

对应上图m_size是3,m_capacity是6

2.动态数组的操作

2.1动态数组的初始化操作

//初始化数组
struct dynamicArray * init_DynamicArray(int capacity);
struct dynamicArray* init_DynamicArray(int capacity)
{
	if (capacity <= 0)
	{
		return NULL;
	}

	//给数组分配空间
	struct dynamicArray* array = malloc(sizeof(struct dynamicArray));//array为数组名,是第一个元素的地址
	if (array == NULL)//判断分配空间操作是否成功,不成功立即退出
	{
		return;
	}
	//给数组初始化
	array->pAddr = malloc(sizeof(void*) * capacity);
	array->m_capacity = capacity;
	array->m_size = 0;

	return array;
}

2.2动态数组的插入操作

//插入数组
void insert_DynamicArray(struct dynamicArray * array, int pos, void * data);
//array为需要做插入操作的数组,所插数据的插入位置为pos、值为data,这里是插入一个数据
void insert_DynamicArray(struct dynamicArray * array, int pos, void * data)
{
	if (array == NULL)//无法对未分配空间的数组做插入操作
	{
		return;
	}
	if (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;//array->m_capacity等价于(*array).m_capacity

		//2、创建新空间
		void ** newSpace = malloc(sizeof(void *)* newCapacity);//sizeof(void *)为每个元素大小

		//3、将原有数据拷贝到新空间下
		memcpy(newSpace, array->pAddr, sizeof(void *) * array->m_capacity);

		//4、释放原有内存空间
		free(array->pAddr);

		//5、更新新空间指向
		array->pAddr = newSpace;

		//6、更新新容量
		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++;
}

2.3动态数组的遍历操作

//打印数组
void foreach_DynamicArray(struct dynamicArray * array, void(*myPrint)(void*));
void foreach_DynamicArray(struct dynamicArray * array, void(*myPrint)(void*))
{
	if (array == NULL)
	{
		return;
	}
	if (myPrint == NULL)
	{
		return;
	}

	for (int i = 0; i < array->m_size; i++)
	{
		myPrint(array->pAddr[i]);
	}
}

2.4动态数组的删除操作

//删除数组  按位置删除
void removeByPos_DynamicArray(struct dynamicArray * array, int pos)
{
	if (NULL == array)
	{
		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--;
}
//按值删除数据
void removeByValue_DynamicArray(struct dynamicArray * array, void * data, int(*myCompare)(void *, void *))
{
	if (array == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}

	for (int i = 0; i < array->m_size; i++)
	{
		if (myCompare(array->pAddr[i], data))
		{
			//如果找到要删除的数据,i就是要删除的具体位置
			removeByPos_DynamicArray(array, i);
			break;
		}
	}
}


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

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

removeByValue_DynamicArray(array, &p, myComparePerson);

2.5销毁数组

//销毁数组
void destroy_DynamicArray(struct dynamicArray* array)
{
	if (array == NULL)
	{
		return;
	}

	if (array->pAddr != NULL)
	{
		free(array->pAddr);
		array->pAddr = NULL;
	}
    
	free(array);
	array = NULL;
}

3.完整代码

头文件:dynamicArray.h

#pragma  once
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

//动态数组结构体
struct dynamicArray
{
	void ** pAddr; //维护真实在堆区创建的数组的指针

	int m_capacity;  // 数组容量

	int m_size;   //数组大小
};

//初始化数组
struct dynamicArray * init_DynamicArray(int capacity);

//插入数组
void insert_DynamicArray(struct dynamicArray * array, int pos, void * data);

//遍历数组
void foreach_DynamicArray(struct dynamicArray * array, void(*myPrint)(void*));

//删除数组  按位置删除
void removeByPos_DynamicArray(struct dynamicArray * array, int pos);

//按值删除数据
void removeByValue_DynamicArray(struct dynamicArray * array, void * data, int(*myCompare)(void *, void *));

//销毁数组
void destroy_DynamicArray(struct dynamicArray* array);

01 动态数组.c

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

#include "dynamicArray.h"

////动态数组结构体
//struct dynamicArray
//{
//	void ** pAddr; //维护真实在堆区创建的数组的指针
//
//	int m_capacity;  // 数组容量
//
//	int m_size;   //数组大小
//};
//
//
////初始化数组
//struct dynamicArray * init_DynamicArray(int capacity)
//{
//	if (capacity <= 0)
//	{
//		return NULL;
//	}
//
//	//给数组分配空间
//
//	struct dynamicArray * array  = malloc(sizeof(struct dynamicArray));
//	if (array == NULL)
//	{
//		return NULL;
//	}
//
//	//给数组初始化
//	array->pAddr = malloc(sizeof(void *)* capacity);
//	array->m_capacity = capacity;
//	array->m_size = 0;
//	
//	return array;
//}
//
////插入数组
//void insert_DynamicArray(struct dynamicArray * array , int pos  , void * data)
//{
//	if ( array == NULL)
//	{
//		return;
//	}
//	if ( 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 ** newSpace = malloc(sizeof(void *)* newCapacity);
//
//		//3、将原有数据拷贝到新空间下
//		memcpy(newSpace, array->pAddr, sizeof(void *)* array->m_capacity);
//
//		//4、释放原有内存空间
//		free(array->pAddr);
//
//		//5、更新新空间指向
//		array->pAddr = newSpace;
//
//		//6、更新新容量
//		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++;
//}
//
//
////遍历数组
//void foreach_DynamicArray(struct dynamicArray * array, void(*myPrint)(void*))
//{
//	if (array == NULL)
//	{
//		return;
//	}
//	if (myPrint == NULL)
//	{
//		return;
//	}
//
//	for (int i = 0; i < array->m_size;i++)
//	{
//		myPrint(array->pAddr[i]);
//	}
//}
//
//
////删除数组  按位置删除
//void removeByPos_DynamicArray(struct dynamicArray * array , int pos)
//{
//	if ( NULL == array)
//	{
//		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--;
//
//}
//
////按值删除数据
//void removeByValue_DynamicArray(struct dynamicArray * array , void * data , int (* myCompare)(void * ,void *))
//{
//	if ( array == NULL)
//	{
//		return;
//	}
//	if ( data == NULL)
//	{
//		return;
//	}
//
//	for (int i = 0; i < array->m_size;i++)
//	{
//		if (myCompare(array->pAddr[i], data))
//		{
//				//如果找到要删除的数据,i就是要删除的具体位置
//			removeByPos_DynamicArray(array, i);
//			break;
//		}
//	}
//
//}
//
////销毁数组
//void destroy_DynamicArray(struct dynamicArray* array)
//{
//	if (array == NULL)
//	{
//		return;
//	}
//
//	if (array->pAddr != NULL)
//	{
//		free(array->pAddr);
//		array->pAddr = NULL;
//	}
//
//
//	free(array);
//	array = NULL;
//}
//

//测试
struct Person
{
	char name[64];
	int age;
};


void myPrintPerson(void *data)
{
	struct Person * p = data;
	printf("姓名: %s 年龄:%d\n", p->name, p->age);

}

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

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

int main(){

	//初始化动态数组
	struct dynamicArray * array = init_DynamicArray(5);

	//准备数据
	struct Person p1 = { "亚瑟", 18 };
	struct Person p2 = { "妲己", 20 };
	struct Person p3 = { "安琪拉", 19 };
	struct Person p4 = { "凯", 21 };
	struct Person p5 = { "孙悟空", 999 };
	struct Person p6 = { "李白", 999};

	printf("插入数据前: 容量:%d  大小:%d\n", array->m_capacity, array->m_size);

	//插入数据
	insert_DynamicArray(array, 0, &p1);
	insert_DynamicArray(array, 0, &p2);
	insert_DynamicArray(array, 1, &p3);
	insert_DynamicArray(array, 0, &p4);
	insert_DynamicArray(array, -1, &p5);
	insert_DynamicArray(array, 2, &p6);

	// 凯 妲己 李白 安琪拉  亚瑟  孙悟空

	//遍历数据
	foreach_DynamicArray(array, myPrintPerson);


	printf("插入数据后: 容量:%d  大小:%d\n", array->m_capacity, array->m_size);


	//测试删除 按位置删除
	removeByPos_DynamicArray(array, 2);
	printf("---------------------\n");
	foreach_DynamicArray(array, myPrintPerson);
	printf("删除数据后: 容量:%d  大小:%d\n", array->m_capacity, array->m_size);

	struct Person  p = { "亚瑟", 18 };
	removeByValue_DynamicArray(array, &p, myComparePerson);
	printf("---------------------\n");
	foreach_DynamicArray(array, myPrintPerson);
	printf("删除数据后: 容量:%d  大小:%d\n", array->m_capacity, array->m_size);


	//array->pAddr = NULL;
	//array->m_capacity = 0;
	//array->m_size = 0;

	//销毁数组
	destroy_DynamicArray(array);
	array = NULL;

	system("pause");
	return EXIT_SUCCESS;
}

dynamicArray.c

#include "dynamicArray.h"

//初始化数组
struct dynamicArray * init_DynamicArray(int capacity)
{
	if (capacity <= 0)
	{
		return NULL;
	}

	//给数组分配空间

	struct dynamicArray * array = malloc(sizeof(struct dynamicArray));
	if (array == NULL)
	{
		return NULL;
	}

	//给数组初始化
	array->pAddr = malloc(sizeof(void *)* capacity);
	array->m_capacity = capacity;
	array->m_size = 0;

	return array;
}

//插入数组
void insert_DynamicArray(struct dynamicArray * array, int pos, void * data)
{
	if (array == NULL)
	{
		return;
	}
	if (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 ** newSpace = malloc(sizeof(void *)* newCapacity);

		//3、将原有数据拷贝到新空间下
		memcpy(newSpace, array->pAddr, sizeof(void *)* array->m_capacity);

		//4、释放原有内存空间
		free(array->pAddr);

		//5、更新新空间指向
		array->pAddr = newSpace;

		//6、更新新容量
		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++;
}


//遍历数组
void foreach_DynamicArray(struct dynamicArray * array, void(*myPrint)(void*))
{
	if (array == NULL)
	{
		return;
	}
	if (myPrint == NULL)
	{
		return;
	}

	for (int i = 0; i < array->m_size; i++)
	{
		myPrint(array->pAddr[i]);
	}
}


//删除数组  按位置删除
void removeByPos_DynamicArray(struct dynamicArray * array, int pos)
{
	if (NULL == array)
	{
		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--;

}

//按值删除数据
void removeByValue_DynamicArray(struct dynamicArray * array, void * data, int(*myCompare)(void *, void *))
{
	if (array == NULL)
	{
		return;
	}
	if (data == NULL)
	{
		return;
	}

	for (int i = 0; i < array->m_size; i++)
	{
		if (myCompare(array->pAddr[i], data))
		{
			//如果找到要删除的数据,i就是要删除的具体位置
			removeByPos_DynamicArray(array, i);
			break;
		}
	}

}

//销毁数组
void destroy_DynamicArray(struct dynamicArray* array)
{
	if (array == NULL)
	{
		return;
	}

	if (array->pAddr != NULL)
	{
		free(array->pAddr);
		array->pAddr = NULL;
	}

	free(array);
	array = NULL;
}

参考资料来源:

黑马程序员

posted @ 2023-05-31 15:45  CodeMagicianT  阅读(38)  评论(0编辑  收藏  举报