STL中的Vector容器就是线性表的数组实现,因为最近学习数据结构,于是手工实现了一遍数组描述的线性表
// 2020/02/14 Tealer.Guo
#include <algorithm> // copy(), find(), copy_backward()
#include <iostream>
#include <iterator> // ostream_iterator<>
// 线性表
// ADT 抽象数据类型
// 纯虚函数
template<typename T>
class linearList {
public:
virtual ~linearList() {};
virtual bool empty() const = 0; // 当线性表为空时,返回0
virtual int size() const = 0; // 返回线性表的元素个数
virtual T& get(int this_index) const = 0; // 返回具有this_index索引的元素
virtual int indexOf(const T& this_elem) const = 0; // 返回元素的索引
virtual void erase(int this_index) = 0; // 删除该索引的元素
virtual void insert(int this_index, const T& this_elem) = 0; // 插入索引和元素
virtual void output(std::ostream& out) const = 0; // 输出线性表
};
// arrayList 线性表数组描述
// 继承ADT
template<typename T>
class arrayList : public linearList<T> {
public:
arrayList(int init_capacity = 10); // 构造函数
arrayList(const arrayList<T>&); // 复制构造函数
~arrayList() { delete [] elements; } // 析构函数
// ADT方法
bool empty() const { return list_size == 0; } // 当线性表为空时,返回0
int size() const { return list_size; } // 返回线性表的元素个数
T& get(int this_index) const; // 返回具有this_index索引的元素
int indexOf(const T& this_elem) const; // 返回元素的索引
void erase(int this_index); // 删除该索引的元素
void insert(int this_index, const T& this_elem); // 插入索引和元素
void output(std::ostream& out) const; // 输出线性表
// 其它方法
int capacity() const { return array_length; } // 返回当前表大小(长度)
protected:
// 访问控制,可以被子类访问
void checkIndex(int this_index) const; // 检查索引,索引无效就抛出异常
T* elements; // 指向表第一个元素地址
int array_length; // 表总长
int list_size; // 当前元素长度
};
// 方法实现
template<typename T>
arrayList<T>::arrayList(int init_capacity) {
// 构造函数
if(init_capacity < 1) {
std::cerr << "The initial capacity mush >= 1 !";
exit(1);
}
array_length = init_capacity;
elements = new T[array_length]; // 建立表
list_size = 0;
}
template<typename T>
arrayList<T>::arrayList(const arrayList<T>& this_arrayList) {
// 复制构造函数
array_length = this_arrayList.array_length;
list_size = this_arrayList.list_size;
elements = new T[array_length]; // 建立新的表
std::copy(this_arrayList.elements, this_arrayList.elements + list_size, elements); // 复制表 copy(起始地址,终止地址,复制目标)
}
template<typename T>
void arrayList<T>::checkIndex(int this_index) const {
// 索引检查
if(this_index < 0 || this_index > list_size) {
std::cerr << "Out of index !";
}
}
template <typename T>
T& arrayList<T>::get(int this_index) const {
// 根据索引取得元素
checkIndex(this_index); // 检查索引
return elements[this_index];
}
template<typename T>
int arrayList<T>::indexOf(const T& this_elem) const {
// 根据元素取得索引
int this_index = (int)(std::find(elements, elements + list_size, this_elem) - elements); // find(起始地址,终止地址,要找的元素)
if(this_index == (list_size)) {
return -1; // 没有找到
} else {
return this_index;
}
}
template<typename T>
void arrayList<T>::erase(int this_index) {
// 删除元素
checkIndex(this_index); // 检查索引
// 移动元素
std::copy(elements + this_index + 1, elements + list_size, elements + this_index);
// 调用析构函数
elements[list_size--].~T(); // 显示调用具体类型自己的析构函数例如~int()
// elements[list_size-=1].~T(); 等于 elements[list_size].~T();list_size -= 1;
// elements[list_size].~T();
// list_size -= 1; // 长度-1
}
template<typename T>
void arrayList<T>::insert(int this_index, const T& this_elem) {
// 插入元素
checkIndex(this_index); // 检查索引
if(list_size == array_length) {
// 表已满
T* temp = new T[array_length * 2]; // 创建一个两倍大的新表
std::copy(elements, elements + list_size, temp); // 将旧表复制到新表
delete [] elements;
elements = temp;
}
// 将元素向后移动一位
std::copy_backward(elements + this_index, elements + list_size, elements + list_size + 1);
elements[this_index] = this_elem; // 写入表
list_size += 1; // 长度+1
}
template<typename T>
void arrayList<T>::output(std::ostream& out) const {
// 输出表
std::copy(elements, elements + list_size, std::ostream_iterator<T>(out, " "));
}
template<typename T>
std::ostream& operator<<(std::ostream& out, arrayList<T>& this_elem) {
// 重载<<
this_elem.output(out);
return out;
}