问题描述
实现一个能够实现自动扩容ArrayList类的封装(不使用C++容器),主要至少具有增加、删除、求长的功能
参考解答
ArrayList.h文件
#ifndef ARRAYLIST_H
#define ARRAYLIST_H
class ArrayList
{
public:
ArrayList();
ArrayList(const int data[], int len);
~ArrayList();
int length()const;
int insert(int idx, int num);
int remove(int idx);
void display()const;
private:
int* arr;
int len;
int capacity;
};
#endif // !ARRAYLIST_H
ArrayList.cpp文件
#include "ArrayList.h"
#include <iostream> // 1、如果不引入一个标准库的话,它会说NULL未定义;2、输出错误信息
using namespace std;
/*
* 功能:
* ArrayList类的缺省构造函数
* 参数:
* void
* 返回值:
* 无
* 作者:
* Excious
**/
ArrayList::ArrayList()
{
this->arr = NULL;
this->len = 0;
this->capacity = 0;
}
/*
* 功能:
* 用数组及其长度构造一个ArrayList对象
* 参数:
* data in 数据数组的首地址
* len in 数据数组的长度(元素个数)
* 返回值:
* 无
* 说明:
* 如果内存不够,可能会出现构建对象失败的情况,控制台将输出“【创建对象时,动态申请空间失败】”
* 作者:
* Excious
**/
ArrayList::ArrayList(const int data[], int len)
{
if (len <= 0)
{
this->arr = NULL;
this->len = 0;
this->capacity = 0;
}
else
{
this->arr = new int[len];
if (NULL == arr)
{
cout << "【创建对象时,动态申请空间失败】" << endl;
this->len = 0;
this->capacity = 0;
return;
}
else
{
this->len = len;
this->capacity = len;
memcpy(arr, data, len * sizeof(int)); // 拷贝内存,据说只要内存上没有重叠部分就能很高效完成
}
}
}
/*
* 功能:
* ArrayList类的析构函数
* 参数:
* void
* 返回值:
* 无
* 作者:
* Excious
**/
ArrayList::~ArrayList()
{
if (this->arr != NULL)
{
delete[] this->arr;
}
}
/*
* 功能:
* 返回当前ArrayList对象中的元素个数
* 参数:
* void
* 返回值:
* 当前ArrayList对象中的元素个数
* 作者:
* Excious
**/
int ArrayList::length()const
{
return this->len;
}
/*
* 功能:
* 在当前ArrayList对象的中的数组下标为idx的元素前插入元素num
* 参数:
* idx in 数组中插入数据的位置
* num in 要插入的元素
* 返回值:
* 0 插入元素成功
* -1 扩容失败,插入失败(控制台输出信息“【创建临时数组时,动态申请空间失败】”)
* -2 插入元素位置非法,插入失败(控制台输出信息“【插入数据的位置不合法】”)
* 说明:
* 扩容后插入使用了函数memcpy,原理是拷贝内存里的内容,据说在拷贝和复制的部分有内存重叠时会出问题
* 不过我这里既然是动态分配空间,只要不是自己复制自己的部分内容,是不会出现内存重叠的情况的
* 作者:
* Excious
**/
int ArrayList::insert(int idx, int num)
{
// 检验插入数据的合法性
if (idx < 0 || idx >= this->len)
{
cout << "【插入数据的位置不合法】" << endl;
return -2;
}
// 检查空间容量是否需要扩容(按照2倍扩容)
if (this->capacity == this->len)
{
this->capacity = this->len * 2;
int* tmp = new int[this->capacity];
if (NULL == tmp)
{
cout << "【创建临时数组时,动态申请空间失败】" << endl;;
this->capacity /= 2;
return -1;
}
else
{
memcpy(tmp, this->arr, idx * sizeof(int));
tmp[idx] = num;
memcpy(tmp + idx + 1, this->arr + idx, (this->len - idx) * sizeof(int));
delete[] this->arr;
this->arr = tmp;
++this->len;
}
}
else
{
for (int i = this->len - 1; i >= idx; --i) // 元素批量后移
{
this->arr[i + 1] = this->arr[i];
}
this->arr[idx] = num;
++this->len;
}
return 0;
}
/*
* 功能:
* 删除当前ArrayList对象的数组中下标为idx的元素
* 参数:
* idx in 要删除的元素在数组中的下标
* 返回值:
* 0 删除元素成功
* -2 删除元素位置非法,插入失败(控制台输出信息“【插入数据的位置不合法】”)
* 作者:
* Excious
**/
int ArrayList::remove(int idx)
{
// 检验删除数据的合法性
if (idx < 0 || idx >= this->len)
{
cout << "【删除数据的位置不合法】" << endl;
return -2;
}
for (int i = idx + 1; i < len; ++i)
{
this->arr[i - 1] = this->arr[i];
}
--this->len;
return 0;
}
/*
* 功能:
* 打印当前ArrayList对象的元素
* 参数:
* void
* 返回值:
* void
* 作者:
* Excious
**/
void ArrayList::display() const
{
int counter = 0;
for (int i = 0; i < this->len; ++i)
{
if (counter != 0) // 控制行首、行尾无空格(空格在元素之间)
{
cout << ' ';
}
cout << this->arr[i];
++counter;
if (0 == counter % 10) // 控制一行10个元素
{
cout << endl;
counter = 0;
}
}
}
main.cpp文件
#include "ArrayList.h"
#include <iostream>
using namespace std;
int main()
{
int data1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int data2[] = { 0 };
ArrayList al_default;
ArrayList al_data1 = ArrayList(data1, sizeof(data1) / sizeof(int));
ArrayList al_data2 = ArrayList(data2, sizeof(data2) / sizeof(int));
cout << "缺省的数组:" << endl;
al_default.display();
cout << "\n根据data1构造的数组:" << endl;
al_data1.display();
cout << "\n根据data2构造的数组:" << endl;
al_data2.display();
cout << "\n\n给al_data1在下标为6的元素前插入数据5:" << endl;
al_data1.insert(6, 5);
al_data1.display();
cout << "\n给al_data1在下标为0的元素前插入数据-1:" << endl;
al_data1.insert(0, -1);
al_data1.display();
cout << "\n\n给al_data2在下标为0的元素前插入数据-1:" << endl;
al_data2.insert(0, -1);
al_data2.display();
cout << "\n给al_data2在下标为1的元素前插入数据2:" << endl;
al_data2.insert(1, 2);
al_data2.display();
cout << "\n给al_data2在下标为2的元素前插入数据3:" << endl;
al_data2.insert(2, 3);
al_data2.display();
cout << "\n给al_data2在下标为3的元素前插入数据4:" << endl;
al_data2.insert(3, 4);
al_data2.display();
cout << "\n给al_data2在下标为-1的元素前插入数据4:" << endl;
al_data2.insert(-1, 4);
al_data2.display();
cout << "\n给al_data2在下标为500的元素前插入数据4:" << endl;
al_data2.insert(500, 4);
al_data2.display();
cout << "\n\n删除al_data2中下标为-1的元素:" << endl;
al_data2.remove(-1);
al_data2.display();
cout << "\n删除al_data2中下标为5的元素:" << endl;
al_data2.remove(5);
al_data2.display();
cout << "\n删除al_data2中下标为2的元素:" << endl;
al_data2.remove(2);
al_data2.display();
cout << "\n删除al_data2中下标为0的元素:" << endl;
al_data2.remove(0);
al_data2.display();
cout << "\n删除al_data2中下标为0的元素:" << endl;
al_data2.remove(0);
al_data2.display();
cout << "\n删除al_data2中下标为0的元素:" << endl;
al_data2.remove(0);
al_data2.display();
cout << "\n删除al_data2中下标为0的元素:" << endl;
al_data2.remove(0);
al_data2.display();
cout << endl;
return 0;
}
整体测试结果如下图所示: