《编码规范和测试方法——C/C++版》作业 ·004——设计一个顺序表

问题描述

实现一个能够实现自动扩容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;
}

整体测试结果如下图所示:

运行结果

发布了49 篇原创文章 · 获赞 9 · 访问量 3121

猜你喜欢

转载自blog.csdn.net/qq_44220418/article/details/104866288