1. アイデア
(1) 最初に配列の初期要素数と値を入力すると、プログラムは要素数の 2 倍のスペースを適用し、残りの 2 倍のスペースは要素の挿入に使用されます。
(2) 要素を挿入するときは、まずスペースが残っているかどうかを確認し、スペースがある場合は挿入し、スペースがない場合は展開します。
(3) このバージョンの拡張戦略は、残りのスペースが十分でない場合、現在の総容量の 2 倍に従って拡張されます。
(4) プログラムの堅牢性を実現するために、データの挿入または削除時に、入力された添字が要素の添字範囲内にない場合は、ユーザーに添字の再入力を求めるプロンプトを表示する必要があります。
(5) Push_back 関数を実行すると、プログラムは現在の容量と同じ数の要素を挿入し、容量を確実に拡張します。
(6) ほとんどの機能はクラスとオブジェクトの形式で実装する必要があります。
2. コードの実装
#include <iostream>
#include <cstdlib>
#include <exception>
using namespace std;
template<typename T> // 函数模板,语法糖
class dyArray
{
private:
//member of data
T * _pData = nullptr;//指针,指向heap中的内存空间首地址
size_t _nSize = 0;//数组中元素个数
size_t _nCapacity = 0;//容量
public:
//member of function
//ctor
dyArray(size_t n=10);
//ctor overload n为申请空间中的元素个数 val为数组中各元素的初始值
dyArray(size_t n,const T & val);
//copy ctor
dyArray(const dyArray & obj);
//dtor
~dyArray();
private:
//memory allocate 分配内存空间
void memset(size_t n)
{
release();
//invoke operator operator new
if(n > 0)
{
_pData = new T[n];
}
}
//dump memory 释放内存空间
void release()
{
if(_pData)
{
delete [] _pData;
_pData = nullptr;
}
}
public:
//member of function
//overload operator []
//nidx为下标索引
T & operator[](size_t nidx)
{
return _pData[nidx];
}
const T & operator[](size_t nidx)const
{
return _pData[nidx];
}
//overload operator=
//rhs source of array
dyArray<T> & operator=(const dyArray<T> & rhs);
public:
//get begin & end
T * begin()
{
return _pData;
}
const T * begin()const
{
return _pData;
}
T * end()
{
return _pData + _nSize;
}
const T * end()const
{
return _pData + _nSize;
}
//get size 获取数组中元素个数
size_t size()const
{
return _nSize;
}
//get capacity 获取数组中容量个数
size_t capacity()const
{
return _nCapacity;
}
//append 在尾部增加一个数据
void push_back(const T & val);
//delete at 删除指定位置(nidx)的元素
bool deleteAt(size_t nidx);
void removeAll();//移除所有的元素
//insert value 在指定位置(nidx)后面插入一个数据val
bool insert(size_t nidx,const T & val);
public:
//conversion function
operator T*()
{
return _pData;
}
operator const T*()const
{
return _pData;
}
private:
//扩容 当战备池用完后,需要扩容时,进行2倍扩容
void expansion();
};
template<typename T>
// 构造函数
dyArray<T>::dyArray(size_t n)
{
// 分配空间
dyArray::memset(n*2);
// 如果n大于0,则正常分配
if(_pData!=nullptr)
{
_nSize=n;
_nCapacity=2*n;
}
}
template<typename T>
dyArray<T>::dyArray(size_t n,const T & val)
{
// 分配空间
memset(n*2);
// 如果n大于0,则正常分配
if(_pData!=nullptr)
{
_nSize=n;
_nCapacity=2*n;
// 赋值
for(int i=0;i<n;i++)
{
_pData[i]=val;
}
}
}
template<typename T>
dyArray<T>::dyArray(const dyArray & obj)
{
_pData=obj._pData;
_nSize=obj._nSize;
_nCapacity=obj._nCapacity;
}
// 析构函数
template<typename T>
dyArray<T>::~dyArray()
{
delete [] _pData;
_pData=nullptr;
}
// 在尾部插入元素
template<typename T>
void dyArray<T>::push_back(const T & val)
{
// 检查战备池是否用完,用完则扩容
if(_nSize==_nCapacity)
{
expansion();
}
_pData[_nSize]=val;
_nSize++;
}
// 删除nidx位置的元素
template<typename T>
bool dyArray<T>::deleteAt(size_t nidx)
{
if(nidx<0 || nidx>=_nSize) return false;
for(int i=nidx;i<_nSize-1;i++)
{
_pData[i]=_pData[i+1];
}
_nSize--;
return true;
}
// 移除所有的元素
template<typename T>
void dyArray<T>::removeAll()
{
_nSize=0;
}
// 在指定位置nidx后面插入一个数据val
template<typename T>
bool dyArray<T>::insert(size_t nidx,const T & val)
{
if(nidx<0 || nidx>=_nSize) return false;
// 检查战备池是否用完
if(_nSize==_nCapacity)
{
expansion(); // 战备池用完,进行扩容
}
for(int i=_nSize;i>nidx+1;i--)
{
_pData[i]=_pData[i-1];
}
_pData[nidx+1]=val;
_nSize++;
return true;
}
// 扩容
template<typename T>
void dyArray<T>::expansion()
{
// 申请一个新空间
size_t newCapacity=2*_nCapacity;
T* newPointer=new T[newCapacity];
// 拷贝旧数据
//memmove(newPointer,_pData,_nSize * sizeof(T));
// 拷贝旧数据也可以这样写
for(int i=0;i<_nSize;i++)
{
newPointer[i]=_pData[i];
}
// 释放旧空间
release();
// 设置成员变量
_pData=newPointer;
_nCapacity=newCapacity;
}
template<typename T>
void display(T * first,T * last)
{
T * start = first;
while(start != last)
{
cout<<*start<<" ";
start++;
}
cout<<endl;
}
int main()
{
int n = 10;
int val = 0;
int val1 = 0;
cout<<"输入起始元素个数和初始值:"<<endl;
cin>>n>>val; // 输入起始元素个数和初始值
size_t npos = 0; // 最长的无符号整数
cout<<"输入插入数据的下标和要插入的值,在此后进行插入:"<<endl;
cin>>npos>>val1; // 输入插入位置和插入的值,在此后进行插入
dyArray<int> ar(n,val);
int * first = ar.begin();
int * last = ar.end();
cout<<"输出插入元素前的状态:"<<endl;
display(first,last);
while(!ar.insert(npos,val1))
{
cout<<"插入失败!请重新输入要插入的位置:"<<endl;
cin>>npos;
}
first = ar.begin();
last = ar.end();
cout<<"输出插入元素后的状态:"<<endl;
display(first,last);
size_t nc = ar.capacity();
for(size_t i=0; i<nc; ++i)
{
ar.push_back(i);
}
cout<<"输出push_back后的元素个数和容量:"<<endl;
cout<<ar.size()<<" "<<ar.capacity()<<endl;
first = ar.begin();
last = ar.end();
cout<<"输出push_back后的状态:"<<endl;
display(first,last);
cout<<"输入要删除的元素下标:"<<endl;
cin>>npos;
while(!ar.deleteAt(npos))
{
cout<<"删除失败!请重新输入要删除的元素下标:"<<endl;
cin>>npos;
}
ar.deleteAt(npos);
cout<<"输出删除指定下标元素后的状态:"<<endl;
first=ar.begin();
last=ar.end();
display(first,last);
cout<<"输出移除所有值后的元素个数和容量:"<<endl;
ar.removeAll();
cout<<ar.size()<<" "<<ar.capacity()<<endl;
return 0;
}
3. プログラム実行結果