/*
面向对象项目:
项目目标:
实现动态可变的数据容器。
项目描述:
我们希望能够做一个能动态修改的容器,可以通过随时添加元素,随时删除元素,达到使用时的灵活性。
我们将结合已经学习到的C++的面向对象的知识,结合一部分的数据结构,实现自己的数据容器。
项目目标:
1、添加元素(末尾添加,指定下标添加)
2、删除元素(按照下标删除、按照元素删除、清空)
3、修改元素(按照下标修改)
4、获取元素(按照下标获取)
5、元素排序
6、元素下标查找
7、将容器中的元素拼接为字符串返回
项目分析:
我们将使用两个版本的可变容器:数组版、双链表版。
这两个版本的数据容器,需要以相同的方式提供数据的访问操作,
在这里,我们使用接口类的方式来完成。
*/
1.定义类模板容器,"QFMutableContainer.h"文件。
#pragma once
using namespace std;
//为了能够容纳各种数据类型的元素。将这个类定义为模板类
template<typename E>
//这个类只是为了给数组和链表版本的容器提供统一的接口,因此,这个类可以直接做成接口类
class QFMutableContainer {
public:
//在末尾添加一个元素
virtual void add(E ele) = 0;
//在指定的下标位插入一个元素
virtual E add(int index, E ele) = 0;
//按照指定的下标删除元素
virtual E remove(int index) = 0;
//按照元素进行删除
virtual bool removeElement(E ele) = 0;
//清空容器
virtual void clear() = 0;
//通过下标修改元素
virtual E set(int index, E ele) = 0;
//通过下标获取元素
virtual E get(int index) = 0;
//排序
virtual void sort() = 0;
//查找元素出现的下标
virtual int index(E ele) = 0;
//将容器中的元素拼接成字符串
virtual string str() = 0;
//返回容器中元素得分数量
virtual int length() = 0;
};
2.定义数组类,"QFMutableArray.hpp"文件。
#pragma once
#pragma once
#include <iostream>
#include <sstream>
#include "QFMutableContainer.h"
using namespace std;
template<typename E>
class QFMutableArray :public QFMutableContainer<E> {
private:
E* array; //用来存储数据的容器
int len; //元素的数量
public:
QFMutableArray();
//在末尾添加一个元素
void add(E ele) override;
//在指定的下标位插入一个元素
E add(int index, E ele) override;
//按照指定的下标删除元素
E remove(int index) override;
//按照元素进行删除
bool removeElement(E ele) override;
//清空容器
void clear() override;
//通过下标修改元素
E set(int index, E ele) override;
//通过下标获取元素
E get(int index) override;
//排序
void sort() override;
//查找元素出现的下标
int index(E ele) override;
//将容器中的元素拼接成字符串
string str() override;
//返回容器中元素得分数量
int length() override;
/*~QFMutableArray() override;*/
~QFMutableArray();
};
template<typename E>
inline QFMutableArray<E>::QFMutableArray()
{
array = new E[0];
len = 0;
}
template<typename E>
inline void QFMutableArray<E>::add(E ele)
{
//添加的思想:
//1.创建一个新的数组,长度为原数组的长度加一。
E* tmp = new E[len + 1];
//2.将原数组中的元素依次拷贝到新的数组中。
for (int i = 0; i < len; i++) {
tmp[i] = array[i];
}
//3.把本次需要添加的元素放入新数组的最后一位。
tmp[len] = ele;
//4.修改元素的数量。
len++;
//5.修改array指针的指向,使其指向新的数组。
delete array;
array = tmp;
}
template<typename E>
inline E QFMutableArray<E>::add(int index, E ele)
{
//添加的思想
//1.创建数组,len+1
E* tmp = new E[len + 1];
//2.将原来的数组中的元素一次拷贝到新的数组中,并且在遇到指定的下标位的时候,需要跳过。
for (int j = 0,i = 0; j < len + 1; j++) {
if (j == index) {
continue;
}
tmp[j] = array[i++];
}
//3.将需要添加的新元素放到新数组中指定的下标位。
tmp[index] = ele;
//4.修改元素的数量。
len++;
//5.修改array指针的指向,使其指向新的数组。
delete array;
array = tmp;
return *array;
}
template<typename E>
inline E QFMutableArray<E>::remove(int index)
{
//1.备份被删除的元素
E ele = array[index];
//2.创建一个新数组,长度减一。
E* tmp = new E[len - 1];
//3.将原来数组中的元素拷贝到新的数组中。
for (int i = 0, j = 0; i < len; i++) {
if (i == index) {
continue;
}
tmp[j++] = array[i];
}
//4.修改原来数组的长度。
len--;
//5.修改array指针的指向,使其指向新的数组。
delete array;
array = tmp;
return ele;
}
template<typename E>
inline bool QFMutableArray<E>::removeElement(E ele)
{
//1.先找到元素的下标
int i = index(ele);
//2.判断元素是否存在;
if (i == -1) {
return false;
}
//3.按照下标来删除元素
remove(i);
return true;
}
template<typename E>
inline void QFMutableArray<E>::clear()
{
//1.将原来的数组置为空;
delete array;
array = new E[0];
//2.重置元素的数量;
len = 0;
}
template<typename E>
inline E QFMutableArray<E>::set(int index, E ele)
{
//1.备份原来的值
E tmp = array[index];
//2.修改原来的值;
array[index] = ele;
//3.返回原来的值
return tmp;
}
template<typename E>
inline E QFMutableArray<E>::get(int index)
{
return array[index];
}
template<typename E>
inline void QFMutableArray<E>::sort()
{
// 外层循环从数组的第一个元素开始,到倒数第二个元素结束
for (int i = 0; i < len - 1; i++) {
// 假设当前元素为最小元素
int minIndex = i;
// 内层循环从外层循环的下一个元素开始,到数组的最后一个元素结束
for (int j = i + 1; j < len; j++) {
// 每次循环比较当前元素和最小元素的大小
if (array[minIndex] > array[j]) {
// 如果当前元素比最小元素小,则更新最小元素的下标
minIndex = j;
}
}
// 如果最小元素的下标不等于当前元素的下标,则交换最小元素和当前元素的位置
if (minIndex != i) {
E tmp = array[i];
array[i] = array[minIndex];
array[minIndex] = tmp;
}
}
}
template<typename E>
inline int QFMutableArray<E>::index(E ele)
{
for (int i = 0; i < len; i++) {
if (ele == array[i]) {
return i;
}
}
return -1;
}
template<typename E>
inline string QFMutableArray<E>::str()
{
if (len == 0) {
return "[]";
}
//创建一个ostringstream的对象,用来拼接元素。
ostringstream oss;
oss << "[";
for (int i = 0; i < len - 1; i++) {
oss << array[i] << ",";
}
oss << array[len - 1] << "]";
return oss.str();
}
template<typename E>
inline int QFMutableArray<E>::length()
{
return len;
}
template<typename E>
inline QFMutableArray<E>::~QFMutableArray()
{
if (array != nullptr) {
delete array;
array = nullptr;
}
}
//template<typename E>
//inline QFMutableArray<E>::~QFMutableArray()
//{
// if (array != nullptr) {
// delete array;
// array = nullptr;
// }
//}
3.主函数
#include <iostream>
#include "QFMutableArray.hpp"
#include "QFMutableContainer.h"
using namespace std;
int main()
{
QFMutableArray<int>* mutableArray = new QFMutableArray<int>();
// 测试添加元素
for (int i = 0; i < 10; i++) {
mutableArray->add(i);
}
cout << mutableArray->str() << endl;
// 测试在指定的下标插入一个元素
mutableArray->add(4, 12);
cout << mutableArray->str() << endl;
// [-33686019,-842150451,-842150451,12,-842150451,-842150451,-842150451,-842150451,-842150451,-842150451,-842150451], for循环循环变量弄错,导致指向不知名域。
// [0,1,2,3,12,4,5,6,7,8,9]
// 测试删除指定下标
cout << mutableArray->remove(5) << endl; // 4
cout << mutableArray->str() << endl; // [0,1,2,3,12,4,5,6,7,8,9],没有对原来的数组进行任何操作,也没有将新的数组赋值给原来的数组。
//[0,1,2,3,12,5,6,7,8,9]
cout << "array[4]=" << mutableArray->index(4) << endl; // -1 不存在
cout << "array[3]=" << mutableArray->index(3) << endl; // 3 第三位
mutableArray->removeElement(3);
cout << mutableArray->str() << endl; //[0,1,2,12,5,6,7,8,9],第一次error,未设置index函数,导致输出结果为删除首位元素的数组。
// 测试清空数组
// mutableArray->clear();
// cout <<"array=" << mutableArray->str() << endl; // []
// 测试修改值
mutableArray->set(0, 1);
cout << "array=" << mutableArray->str() << endl; // array=[1,1,2,12,5,6,7,8,9]
// 获取值
cout << "array[5]=" << mutableArray->get(5) << endl; // array[5]=6
//选择排序
mutableArray->sort();
cout << "array=" << mutableArray->str() << endl; //array=[1,1,2,5,6,7,8,9,12],
return EXIT_SUCCESS;
}