【数据结构与算法】动态数组

【数据结构与算法】动态数组


文章目录


前言

本篇文章就动态数组的设计,动态数组的初始化,动态数组插入和遍历功能实现,动态数组删除和销毁功能实现,动态数组分文件编写。


一、动态数组的设计

  • 插入元素算法
    判断线性表是否合法
    判断插入位置是否合法
    判断空间是否满足
    把最后一个元素到插入位置的元素后移一个位置
    将新元素插入
    线性表长度加1
  • 获取元素操作
    判断线性表是否合法
    判断位置是否合法
    直接通过数组下标的方式获取元素
  • 删除元素算法
    判断线性表是否合法
    判断删除位置是否合法
    将元素取出
    将删除位置后的元素分别向前移动一个位置
    线性表长度减1

元素的插入

元素的删除


二、动态数组的初始化

动态数组结构体

c 复制代码
// 动态数组结构体
struct dynamicArray
{
	void** pAddr;	//维护真实在堆区创建的数组的指针数组每个元素为void*
	int m_capacity;	//数组容量
	int m_size;		//数组大小
};

动态数组初始化

c 复制代码
// 初始化数组
struct dynamicArray* init_DynamicArray(int capacity)
{
	if (capacity <= 0)
	{
		return NULL;
	}
	
	//给数组分配空间
	struct dynamicArray* array = malloc(sizeof(struct dynamicArray));
	if (array == NULL)
	{
		return;
	}

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

三、动态数组插入和遍历功能实现

插入数组

c 复制代码
//插入数组
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++;
}

遍历数组

c 复制代码
//遍历数组
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]);
	}
}

测试

c 复制代码
//测试
struct Person
{
	char name[64];
	int age;
};

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

}

运行结果


四、动态数组删除和销毁功能实现

按位置删除

c 复制代码
//删除数组  1、按位置删除
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--;
}

测试

c 复制代码
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);


}

测试结果:

按值删除

c 复制代码
//删除数组  2、按值删除数据
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;
		}
	}
}

测试

c 复制代码
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);



}

测试结果

销毁数组

c 复制代码
//销毁数组
void destroy_DynamicArray(struct dynamicArray* array)
{
	if (array == NULL)
	{
		return;
	}
	if (array->pAddr != NULL)
	{
		free(array->pAddr);
		array->pAddr = NULL;
	}

	free(array);
	array = NULL;
}

五、动态数组分文件编写

dynamicArray.h

c 复制代码
#define  _CRT_SECURE_NO_WARNINGS 1
#pragma  once
#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);

dynamicArray.c

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;
}

动态数组.c

c 复制代码
#include "dynamicArray.h"

//测试
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);


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

	return 0;
}

总结

到这里这篇文章的内容就结束了,谢谢大家的观看,如果有好的建议可以留言喔,谢谢大家啦

相关推荐
zero_one_Machel5 分钟前
leetcode73矩阵置零
算法·leetcode·矩阵
青椒大仙KI1136 分钟前
24/9/19 算法笔记 kaggle BankChurn数据分类
笔记·算法·分类
^^为欢几何^^40 分钟前
lodash中_.difference如何过滤数组
javascript·数据结构·算法
豆浩宇40 分钟前
Halcon OCR检测 免训练版
c++·人工智能·opencv·算法·计算机视觉·ocr
浅念同学1 小时前
算法.图论-并查集上
java·算法·图论
何不遗憾呢1 小时前
每日刷题(算法)
算法
立志成为coding大牛的菜鸟.1 小时前
力扣1143-最长公共子序列(Java详细题解)
java·算法·leetcode
鱼跃鹰飞1 小时前
Leetcode面试经典150题-130.被围绕的区域
java·算法·leetcode·面试·职场和发展·深度优先
liangbm31 小时前
数学建模笔记——动态规划
笔记·python·算法·数学建模·动态规划·背包问题·优化问题
潮汐退涨月冷风霜1 小时前
机器学习之非监督学习(四)K-means 聚类算法
学习·算法·机器学习