原理介绍

我们利用万能指针来实现动态数组,数组元素类型可以是任意类型,因为我们只维护用户提供的数据的地址,所以可以用万能指针来接受,这样就实现了类似C++中的模板功能了

先说说动态数组和静态数组静态数组一旦建立它的空间是不可变的,比如我们在栈上开辟的空间,一旦开辟,长度就不可变。如果我们用malloc在堆区开辟的数组,如果当我们检测到数组已经满了,我们可以重新开辟一块更大的空间,将原有的数据拷贝到新的空间,这样就实现动态数组的效果了

实现算法预览

DynamicArray.h

#pragma once
#ifndef __DYNAMICARRAY_H__
#define __DYNAMICARRAY_H__
#define _CRT_SECURE_NO_WARNINGS
//动态数组
typedef struct DynamicArray
{void** pArr;//数组元素具体存储位置,由于不知道用户存储的数据类型和数据位置统一用void*来指向用户存储的每一个元素int m_size;//数组大小int m_capacity;//数组容量
}DynamicArray;//初始化动态数组
DynamicArray* Init_DynamicArray(int capacity);//动态数组插入数据
//模拟数组pos范围0  ~  arr->m_size - 1
int InsertByIndex_DynamicArray(DynamicArray* arr, void * data, int pos);//动态数组进行遍历
void Foreach_DynamicArray(DynamicArray* arr, void(*Foreach_Function)(void*));//动态数组删除元素根据元素下标
int RemoveByIndex_DynamicArray(DynamicArray* arr, int pos);//动态数组删除元素根据元素的值
int RemoveByValue_DynamicArray(DynamicArray* arr, void* data, int(*compare)(void* data1, void* data2));//动态数组销毁
int Destroy_DynamictArray(DynamicArray* arr);#endif // !__DYNAMICARRAY_H__

实现代码展示

DynamicArray.c

#include <stdio.h>
#include <stdlib.h>
#include "DynamicArray.h"//初始化动态数组
DynamicArray* Init_DynamicArray(int capacity)
{DynamicArray* arr = (DynamicArray*)malloc(sizeof(DynamicArray));if (NULL == arr){return NULL;}arr->m_capacity = capacity;arr->pArr = malloc(sizeof(void*)*capacity);arr->m_size = 0;return arr;
}
//动态数组插入数据
//模拟数组pos范围0  ~  arr->m_size - 1
int InsertByIndex_DynamicArray(DynamicArray* arr, void * data, int pos)
{if (NULL == arr || NULL == data){return 0;}//位置非法 进行尾插if (pos < 0 || pos >= arr->m_size){pos = arr->m_size;}//判断数组是否满载if (arr->m_size >= arr->m_capacity){//进行扩容int newCapacity = arr->m_capacity * 2;//arr->pArr = (void**)realloc((void*)arr->pArr, newCapacity);//数据复制有问题 error//手动复制void** pArr = malloc(sizeof(void*)*newCapacity);for (int i = 0; i < arr->m_capacity; i++){pArr[i] = arr->pArr[i];}if (arr->pArr != NULL){free(arr->pArr);arr->pArr = NULL;}arr->pArr = pArr;arr->m_capacity = newCapacity;}//将插入位置以及其后的数组元素往后移动一位for (int i = arr->m_size - 1; i >= pos; i--){arr->pArr[i + 1] = arr->pArr[i];}//将新元素进行插入arr->pArr[pos] = data;arr->m_size++;return 1;
}
//动态数组进行遍历
void Foreach_DynamicArray(DynamicArray* arr, void(*Foreach_Function)(void*))
{if (NULL == arr){return;}for (int i = 0; i < arr->m_size; i++){//并不知道用户的数据类型,让用户自己提供遍历数组元素的回调函数Foreach_Function(arr->pArr[i]);}return;
}
//动态数组删除元素根据元素下标
int RemoveByIndex_DynamicArray(DynamicArray* arr, int pos)
{//arr 为NULL 和传入位置非法 返回if (NULL == arr || pos<0 || pos>arr->m_size - 1){return 0;}//将删除位置后面的所有元素往前移一位进行覆盖for (int i = pos; i < arr->m_size - 1; i++){arr->pArr[i] = arr->pArr[i + 1];}arr->m_size--;return 1;
}
//动态数组删除元素根据元素的值
int RemoveByValue_DynamicArray(DynamicArray* arr, void* data, int(*compare)(void* data1, void* data2))
{//arr 为NULL 和传入位置非法 返回if (NULL == arr || NULL == arr){return 0;}for (int i = 0; i < arr->m_size; i++){if (compare(arr->pArr[i], data)){RemoveByIndex_DynamicArray(arr, i);break;}}return 1;
}
//动态数组销毁
int Destroy_DynamictArray(DynamicArray* arr)
{if (NULL == arr){return 0;}if (arr->pArr != NULL){free(arr->pArr);arr->pArr = NULL;}free(arr);arr = NULL;return 1;
}

Main.c

#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "DynamicArray.h"//使用结构体数据类型 测试动态数组
typedef struct Hero
{char name[64];int age;
}Hero;int Compare_Hero(void* hero1, void* hero2)
{Hero* h1 = (Hero*)hero1;Hero* h2 = (Hero*)hero2;return h1->age == h2->age && strcmp(h1->name, h2->name) == 0;
}
void Print_Hero(Hero* hero)
{if (NULL == hero){return;}printf("name:%s,age:%d\n",hero->name,hero->age);return;
}
int main(int argc, char *argv[])
{Hero h1 = { "关羽",38 };Hero h2 = { "张飞",39 };Hero h3 = { "赵云",29 };Hero h4 = { "许褚",19 };Hero h5 = { "鲁肃",25 };Hero h6 = { "周瑜",27 };DynamicArray* arr = Init_DynamicArray(5);printf("插入数据前动态数组容量:%d\n", arr->m_capacity);InsertByIndex_DynamicArray(arr, &h1, 0);InsertByIndex_DynamicArray(arr, &h2, 0);InsertByIndex_DynamicArray(arr, &h3, 0);InsertByIndex_DynamicArray(arr, &h4, 2);InsertByIndex_DynamicArray(arr, &h5, 100);InsertByIndex_DynamicArray(arr, &h6, 1);Foreach_DynamicArray(arr, Print_Hero);//正确顺序:赵云 周瑜 张飞 许褚 关羽 鲁肃printf("插入数据后动态数组容量:%d\n", arr->m_capacity);printf("删除index = 3的元素\n");RemoveByIndex_DynamicArray(arr, 3);Foreach_DynamicArray(arr, Print_Hero);printf("删除赵云\n");RemoveByValue_DynamicArray(arr, &h3, Compare_Hero);Foreach_DynamicArray(arr, Print_Hero);Destroy_DynamictArray(arr);return 0;
}

运行结果检测

数据结构与算法:动态数组(利用万能指针实现任意类型数组操作)相关推荐

  1. 数据结构和算法动态可视化

    数据结构和算法动态可视化 (Chinese) 刚发现的一个很有意思的网站,可以帮助理解算法和数据结构 数据结构的话基本上都齐了,可以选择翻译成中文

  2. java 数组的长度如何增加,用Java动态增加任意类型数组的长度

    用Java动态增加任意类型数组的长度 如果你需要动态增加数组大小: public  int[]  expandArray(int[]  a,  int  size)  { if  (size  < ...

  3. java数组及Arrays创建一个int 类型数组 数组元素由键盘录入,每次打印插入排序的结果(数组扩容,数组排序,键盘录入)

    @author silence丶你的名字 java数组及Arrays创建一个int 类型数组 数组元素由键盘录入,每次打印插入排序的结果 初始数组元素1 for死循环 获取用户录入的数据,如果为952 ...

  4. 数据结构与算法:单链表(利用万能指针实现对任意类型数据进行操作)

    前言 C语言的指针真的很强大,万能指针更强大,可以指向任意类型的数据.在上篇博客 数据结构与算法:单链表(超详细实现)中用C语言实现了单链表的相关算法,不过却有局限性 只能针对某一种数据类型还是不够强 ...

  5. 数据结构和算法详解(二)——线性表(数组、链表、栈、队列)

    一.数组 线性表:   线性表就是数据排成像一条线一样的结构.每个现行表上的数据最多只有前和后两个方向.常见的线性表结构:数组,链表.队列.栈等. 什么是数组: 数组(Array)是一种线性表数据结构 ...

  6. 计算机基础数据结构和算法动态可视化展示网站收录

    计算机中有很多数据结构.算法对于小白来说非常难理解,交互式动画一步步展示整个过程可以帮助我们快速准确地理解这些算法.我们整理了12个可动态交互和展示常见数据结构和排序.图算法等网站,总计12个 收录到 ...

  7. 数据结构与算法之复制含有随机指针节点的链表和两个链表相交的一系列问题

    数据结构与算法复制含有随机指针节点的链表和两个链表相交的一系列问题 目录 复制含有随机指针节点的链表 两个链表相交的一系列问题 1. 复制含有随机指针节点的链表 题目概述 思路:创建一个HashMap ...

  8. 记一次数据结构与算法作业:利用循环和递归输出1-N的正整数的程序分析比较

    随便记录一次数据结构与算法的分析作业,内容为分析循环和递归实现输出1-N的正整数的对比.从时间和空间上分析了两种方式实现的递归方法和循环区别. 一.数据记录图表 二.分析 第一张图表制作时由于在打游戏 ...

  9. c语言数组数据用指针查找,c语言数组与指针_指针篇_2011.ppt

    c语言数组与指针_指针篇_2011 指 针 6.2 指针的概念6.3 指针与数组6.4 字符串的指针6.5 指针数组和指向指针的指针;6.2.1 地址与指针的概念 ;指针的概念;内存地址;2.数组与地 ...

最新文章

  1. PASCAL VOC工具包解读
  2. docker pip 换源_Docker 部署 jupyterlab 3.0.3
  3. 【python】简单记录
  4. python 文件操作 os 如何检索文件夹内文件数量
  5. centos中安装mysql5.6_CentOS中安装MySQL5.6报错的解决方法
  6. bufferedreader读取中文乱码_python之pandas模块关于csv文件乱码问题解决
  7. 华为云ROMA,联接企业应用的现在与未来
  8. 读书笔记之 数据框操作与常用函数
  9. 数据流中的中位数 Find Median from Data Stream
  10. HBuilder实现WiFi调试Android
  11. 多线程等待/通知机制
  12. 如何安装Virtual Box的VBox Guest Additions扩展程序
  13. 汽车主要电子控制系统模块
  14. Unity3D 学习笔记(六) 手柄配置
  15. MATLAB批量改变图片大小
  16. java获取月份有几周_java 获取当前日期是本月的第几周,且当月一共有几周
  17. STM32__04—PMW呼吸灯
  18. C++的友元函数,友元类及#pragma once的作用
  19. 口碑最好的国产蓝牙耳机,2021国产最好用的蓝牙耳机
  20. 畅想小组KTV点歌系统简介

热门文章

  1. PHP个人博客网站设计 学生PHP个人博客网页源码 PHP MYSQL动态网站作品
  2. xgboost算法_XGBoost算法可能会长期占据你的视野!
  3. beautifulsoup_BeautifulSoup爬虫了解一下
  4. Python笔记-相关性分析(连续变量和分类变量)
  5. Python文档阅读笔记-OpenCV中Template Matching
  6. MySQL笔记-MHA(Master High Availability)搭建
  7. Qt文档阅读笔记-加载HeightMap(高度图)构造3D地形图
  8. Qt文档阅读笔记-Q_ASSERT的另外一总用法(大佬用法)
  9. 反汇编基础-加法的求值过程(各种类型)
  10. 6.6.2赫夫曼编码