数据结构-动态数组
在C中所有的数组大小都是固定的,在未知数据大小的情况下不方便提前设置数组大小,所以采用一种动态数组的方式;
个人感觉:所谓动态数组便是使用2级指针,并且使用这个2级指针所存储的空间充当数组去存储数据的指针,并且不断的申请与析构,拷贝复制去满足存储未知的数据;
先上使用C++封装的动态数组代码
头文件:
class DynamicClass
{
public:
DynamicClass();
~DynamicClass();
//创建动态数组 参数为需要传入的动态数组大小
void CreateDyanmicVec( int dynamicMaxSize);
//添加数据, 参数为数据和位置
void PushBackDynamicVec(void * data,int pos);
//遍历数组,传入一个函数指针,交由别处针对数据进行打印验证
void ErgodicityDynamicVec(void(*CountData)(void * data));
//按照位置删除数据
void EraseDynamicVec(int pos);
//按照数据删除数据,提供函数指针交由别处判断两组数据是否相等
void EraseDynamicVec(void * Data, bool(*EqualityData)(void * data, void * data2));
//清理动态数组,这个位置如果该类对象声明的时候完成的是深拷贝,则可以写入到析构函数中等待最后在进行析构,这里有些懒,也为了方便步骤,没有进行深拷贝的构造函数,单独写在了这个位置
void ClearDynamicVec();
private:
//动态数组
void ** _DynamicVec;
//数组最大值
int _DynamicVecMaxSize;
//当前数组位置
int _DynamicVecPos;
};
CPP:
#include "DynamicClass.h"
#include <stdlib.h>
#include <wchar.h>
DynamicClass::DynamicClass()
{
_DynamicVec =0;
_DynamicVecMaxSize = 0;
_DynamicVecPos = 0;
}
DynamicClass::~DynamicClass()
{
}
void DynamicClass::CreateDyanmicVec(int dynamicMaxSize)
{
if (dynamicMaxSize == 0)
{
return;
}
void ** Vec = static_cast<void **>(malloc(sizeof(void *)*dynamicMaxSize));
if (Vec)
{
_DynamicVec = Vec;
_DynamicVecMaxSize = dynamicMaxSize;
}
}
void DynamicClass::PushBackDynamicVec(void * data, int pos)
{
//如果数据为空则推出
if (data == NULL)
{
return;
}
//如果数组为空则推出
if (_DynamicVec == NULL)
{
return;
}
//存储是否已经为最后一位,如果已经存储到数组的最大个数,则证明需要开辟空间
if (_DynamicVecMaxSize <= _DynamicVecPos)
{
int DynamicVecMaxSize = _DynamicVecMaxSize * 2;
void ** D = static_cast<void **>(malloc(sizeof(void*)*DynamicVecMaxSize));
if (D)
{
_DynamicVecMaxSize = DynamicVecMaxSize;
memcpy(D,_DynamicVec,sizeof(void *)*_DynamicVecPos);
free(_DynamicVec);
_DynamicVec = D;
}
}
//如果数组为空则推出
if (_DynamicVec == NULL)
{
return;
}
//数据存储位置检查 如果大于当前存储位置的最大值并且小于当前数组的最大值,则末端插入
if (pos>_DynamicVecPos&&pos<_DynamicVecMaxSize)
{
pos = _DynamicVecPos + 1;
}
//从末端开始后移,直至后移到pos位置空出
for (int i = _DynamicVecPos-1; i >= pos; i--)
{
_DynamicVec[i + 1] = _DynamicVec[i];
}
#if 1
_DynamicVec[pos] = data;
#else
//此处原本想要考虑一种可以存储局部变量的方法,但暂时未想到解决办法
memcpy(_DynamicVec[pos], data, sizeof(data));
#endif
_DynamicVecPos = _DynamicVecPos + 1;
}
void DynamicClass::ErgodicityDynamicVec(void(*CountData)(void * data))
{
//从末端开始后移,直至后移到pos位置空出
for (int i = 0; i < _DynamicVecPos; i++)
{
void * CData = _DynamicVec[i];
CountData(CData);
}
}
void DynamicClass::EraseDynamicVec(int pos)
{
//如果数组为空则推出
if (_DynamicVec == NULL)
{
return;
}
//如果大于当前存储值则退出
if (pos>_DynamicVecPos)
{
return;
}
//从pos位置开始,向前覆盖,此处不可以析构,因为空间在数组中
for (int i = pos; i < _DynamicVecPos; i++)
{
_DynamicVec[i] = _DynamicVec[i + 1];
}
_DynamicVecPos = _DynamicVecPos - 1;
}
void DynamicClass::EraseDynamicVec(void * Data, bool(*EqualityData)(void * data, void * data2))
{
//如果数组为空则推出
if (_DynamicVec == NULL)
{
return;
}
if (Data == NULL)
{
return;
}
for (int i = 0; i < _DynamicVecPos;i++)
{
if (EqualityData(_DynamicVec[i],Data))
{
EraseDynamicVec(i);
return;
}
}
}
void DynamicClass::ClearDynamicVec()
{
if (_DynamicVec)
{
free(_DynamicVec);
_DynamicVec = NULL;
}
}
在上测试数据:
#pragma once
#include <iostream>
#include <string>
class DynamicTextStr
{
public:
DynamicTextStr();
DynamicTextStr(std::string Name, int Number);
~DynamicTextStr();
static void CountData(void * data);
static bool EqualityData(void * data, void * data2);
std::string _Name;
int _Number;
};
测试数据类实现
#include "DynamicTextStr.h"
DynamicTextStr::DynamicTextStr()
{
}
DynamicTextStr::DynamicTextStr(std::string Name, int Number)
{
_Name = Name;
_Number = Number;
}
DynamicTextStr::~DynamicTextStr()
{
}
void DynamicTextStr::CountData(void * data)
{
if (DynamicTextStr *TextStr = static_cast<DynamicTextStr *>(data))
{
std::cout << "Name :" << TextStr->_Name << " Number :" << TextStr->_Number << std::endl;
}
}
bool DynamicTextStr::EqualityData(void * data, void * data2)
{
if (DynamicTextStr *TextStr = static_cast<DynamicTextStr *>(data))
{
if (DynamicTextStr *TextStr1 = static_cast<DynamicTextStr *>(data2))
{
if (TextStr->_Name == TextStr1->_Name)
{
if (TextStr->_Number == TextStr1->_Number)
{
return true;
}
}
}
}
return false;
}
main函数
#include <QtCore/QCoreApplication>
#include "DynamicClass.h"
#include "DynamicTextStr.h"
int main(int argc, char *argv[])
{
DynamicClass TextClass;
//先设置为三个,方便测试第四个的数据添加
TextClass.CreateDyanmicVec(3);
DynamicTextStr Str1 = DynamicTextStr("张三", 13);
DynamicTextStr Str2 = DynamicTextStr("李四", 14);
DynamicTextStr Str3 = DynamicTextStr("王五", 15);
DynamicTextStr Str4 = DynamicTextStr("麻溜", 16);
TextClass.PushBackDynamicVec(&Str1, 0);
TextClass.PushBackDynamicVec(&Str2, 0);
TextClass.PushBackDynamicVec(&Str3, 0);
TextClass.PushBackDynamicVec(&Str4, 0);
TextClass.ErgodicityDynamicVec(DynamicTextStr::CountData);
std::cout << "------------------------ " << std::endl;
TextClass.EraseDynamicVec(0);
TextClass.EraseDynamicVec(&Str2, DynamicTextStr::EqualityData);
TextClass.ErgodicityDynamicVec(DynamicTextStr::CountData);
std::cout << "------------------------ " << std::endl;
TextClass.ClearDynamicVec();
}
运行结果
补充:
动态数组用于C++实现,仔细观察main函数以发现必须使得所存储的数据为全局变量,对象存储后不可以发生析构,否则在打印的时候会出现问题;
所以可以进行一些优化与完善;当然在已知数据类型的情况下可以完善并且解决,但在未知的情况下,就需要与其他相互配合了;