数据结构---动态数组

 一、数据结构基本理论

数据结构是相互之间存在一种或多种特定关系的数据元素的集合。强调数据元素之间的关系

算法五个特性:
        输入、输出、有穷、确定、可行

数据结构分类:
        逻辑结构:集合、线性结构、树形结构、图形结构

        物理结构:顺序存储、链式存储、索引存储、散列存储(哈希存储)

二、动态数组实现

1.设计

        struct dynamicArray

        属性:
        void ** pAddr  维护真实在堆区创建的数组的指针

        int capacity;  数组容量·
        int m_size;  数组大小

2.动态数组初始化

struct dynamicArray* init_DynamicArray(int capacity);

3.插入数组

void insert_DynamicArray(struct dynamicArray* array, int pos, void* data);

4.遍历数组

void foreach_DynamicArray(struct dynamicArray* array, void(*myPrint)(void*));

5.删除数组

按位置删除

void removeByPos_DynamicArray(struct dynamicArray* array, int pos);

按值删除数据

void removeByValue_DynamicArray(struct dynamicArray* array, void* data, int(*myCompare)(void*, void*));

6.销毁数组

void destroy_DynamicArray(struct dynamicArray* array);

代码如下: 

#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)
{
	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);

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

	return 0;
}

三、实现分文件编写 

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

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

测试:

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/599204.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Baidu Comate:你的智能编程伙伴,编程界的AI革命者

文章目录 Baidu Comate 介绍Baidu Comate下载安装Baidu Comate 实操体验代码解释函数注释行间注释调优建议生成单测注释生成实时续写常用快捷方式智能对话问答 Baidu Comate 建议改进Baidu Comate 体验总结 Baidu Comate 介绍 Baidu Comate 智能编码助手 是基于文心大模型&…

【nginx 开发】nginx安装,Nginx介绍

Nginx基础介绍 Nginx反向代理负载均衡动静分离 Nginx的安装NginxNginx常用命令Nginx配置文件 Nginx Nginx是一个高性能的Http和反向代理服务器&#xff0c;特点是占有内存少&#xff0c;并发能力强&#xff0c;Nginx可以作为静态页面的web服务器&#xff0c;Nginx专为性能优化…

4G工业路由器快递柜应用案例(覆盖所有场景)

快递柜展示图 随着电商的蓬勃发展,快递行业迎来高速增长。为提高快递效率、保障快件安全,智能快递柜应运而生。但由于快递柜部署环境复杂多样,网络接入成为一大难题。传统有线宽带难以覆盖所有场景,而公用WiFi不稳定且存在安全隐患。 星创易联科技有限公司针对这一痛点,推出了…

我独自升级崛起在哪下载 我独自升级崛起客户端下载教程

定于5月8日全球盛放的《我独自升级&#xff1a;崛起》——这一激动人心的动作角色扮演游戏巨作&#xff0c;汲取了同名动漫及网络漫画的精髓&#xff0c;誓将以其无与伦比的魅力&#xff0c;引领玩家迈入一个探索深远、规模宏大的奇幻之旅。游戏构筑在一个独一无二的网络武侠世…

JavaScript:正则表达式属于字符串吗-不属于/字符串转正则表达式的两种方法

一、需求描述 js 字符串转正则表达式 二、理解正则表达式属于字符串吗? 正则表达式不属于字符串&#xff0c;它是一种用于匹配、查找和操作文本的模式。正则表达式是一种特殊的语法&#xff0c;用于描述字符串的特征。通过使用正则表达式&#xff0c;可以检查一个字符串是否…

项目计划书(Word原件)

项目开发计划包括项目描述、项目组织、成本预算、人力资源估算、设备资源计划、沟通计划、采购计划、风险计划、项目过程定义及项目的进度安排和里程碑、质量计划、数据管理计划、度量和分析计划、监控计划和培训计划等。 软件资料清单列表部分文档&#xff1a; 工作安排任务书…

如何有效识别限界上下文?

在实施DDD的过程中&#xff0c;识别限界上下文是一大难点&#xff0c;但也并非无章可循。在本文内容中&#xff0c;我们将分别从业务维度、工作维度以及技术维度进行展开&#xff0c;讨论如何有效识别限界上下文的方法和技巧。 从业务维度识别限界上下文 从业务维度识别限界上…

羊大师解析,鲜为人知的羊奶冷知识

羊大师解析&#xff0c;鲜为人知的羊奶冷知识 羊奶的脂肪球更小&#xff1a;相较于牛奶&#xff0c;羊奶中的脂肪球直径更小&#xff0c;这有助于其更快地被人体消化和吸收。 羊奶含有更多的中链脂肪酸&#xff1a;羊奶中含有较多的中链脂肪酸&#xff08;MCT&#xff09;&am…

安装nginx-1.25.5与ngx_http_headers_more_filter_module模块

#下载nginx的代码 curl -O http://nginx.org/download/nginx-1.25.5.tar.gz #下载headers-more-nginx-module代码 git clone https://github.com/openresty/headers-more-nginx-module#解压 tar -xzf nginx-1.25.5.tar.gzcd nginx-1.25.5#--add-dynamic-module 下载下来的目录 …

Al Agent:开启智能化未来的关键角色,让机器更智能的为我们服务

文章目录 &#x1f680;Al Agent是什么&#x1f4d5;Al Agent的工作原理与技术&#x1f4aa;Al Agent应用领域&#x1f680;智能家居应用&#x1f308;医疗健康领域⭐金融服务行业&#x1f302;交通运输管理&#x1f3ac;教育培训应用 &#x1f512;Al Agent优势与挑战✊Al Age…

移动端自适应

基本实现核心思想 基本原则上是&#xff0c;布局更多地使用flex&#xff0c;然后尺寸使用rem&#xff0c;vw&#xff0c;vh为单位如果是根据不同的屏幕需要有不同的布局了&#xff0c;一般通过检测屏幕尺寸换不同的站点或者媒体查询使用css rem 以html字体太小为1rem的大小&…

LM4562NA 直插DIP8双运放 音频hifi运算放大器

LM4562NA是一款高性能音频运算放大器&#xff0c;其应用领域主要集中在音频和声音处理方面&#xff0c;包括但不限于&#xff1a; 1. 专业录音设备&#xff1a;在录音棚、广播电台和电视台等专业环境中&#xff0c;用于信号放大和处理&#xff0c;确保高质量的声音录制和传输…

揭秘数据可视化:五款利器助力决策

在当今这个数据驱动的时代&#xff0c;数据可视化已成为企业决策、数据分析不可或缺的一部分。通过直观、生动的图形、图像&#xff0c;数据可视化能够更快速、更准确地传达信息&#xff0c;帮助企业洞察数据背后的价值。本文将为您介绍几款优秀的数据可视化工具。 一、山海鲸…

docker-compose编排集成工具,consul服务更新与发现

一、引言 我们知道使用一个 Dockerfile 模板文件可以定义一个单独的应用容器&#xff0c;如果需要定义多个容器就需要服务编排。服务编排有很多种技术方案&#xff0c;今天给大家介绍 Docker 官方产品 Docker-Compose Dockerfile 可以定义一个单独的应用容器&#xff1…

图片编辑工具-Gimp

一、前言 GIMP&#xff08;GNU Image Manipulation Program&#xff09;是一款免费开源的图像编辑软件&#xff0c;具有功能强大和跨平台的特性。 GIMP作为一个图像编辑器&#xff0c;它提供了广泛的图像处理功能&#xff0c;包括但不限于照片修饰、图像合成以及创建艺术作品…

uni-app安卓本地打包个推图标配置

如果什么都不配置&#xff0c;默认的就是个推小鲸鱼图标 默认效果 配置成功效果 个推图标配置 新建目录 drawable-hdpi、drawable-ldpi、drawable-mdpi、drawable-xhdpi、drawable-xxhdpi、drawable-xxxhdpi 目录中存放图标 每个目录中存放对应大小的图标&#xff0c;大图…

Day28:ElasticSearch入门、Spring整合ES、开发社区搜索功能

ElasticSearch入门 Elasticsearch简介 一个分布式的、Restful风格的搜索引擎。支持对各种类型的数据的检索&#xff08;非结构化的也可以&#xff09;。搜索速度快&#xff0c;可以提供实时的搜索服务。便于水平扩展&#xff08;集群式部署&#xff09;&#xff0c;每秒可以处…

分享三维地理模型制作实践

前言 地理信息系统&#xff08;GIS&#xff09;是一种用于捕获、存储、检查和显示与地球表面位置相关的数据的计算机系统。GIS可以在一张地图上显示许多不同类型的数据&#xff0c;如街道、建筑物和植被。这使人们能够更容易地看到、分析和理解模式和关系。 实践 从地理空间…

正在载入qrc文件 指定的qrc文件无法找到。您想更新这个文件的位置么?

打开Qt的ui文件&#xff0c;弹出提示框 如果需要用到qrc文件&#xff0c;选择Yes&#xff0c;再选择qrc文件所在的位置&#xff1b;如果不需要qrc文件&#xff0c;可以选择No&#xff0c;然后用普通文本编辑器打开&#xff0c;将“ <resources> <include location&q…

经典面试题---环形链表

1. 环形链表1. - 力扣&#xff08;LeetCode&#xff09; 要解决这道题&#xff0c;我们首先要挖掘出带环的链表与不带环的链表之间的差别。 以此&#xff0c;才能设计出算法来体现这种差别并判断。 二者最突出的不同&#xff0c;就是不带环的链表有尾结点&#xff0c;也就是说…