一个线性表(linearList)可以用一个抽象数据类型(ADT)来说明。
抽象数据类型linearList{
实例
有限个元素的有序集合
操作
empty():若表空,返回true
size():返回表中元素的个数
get(index):返回线性表中索引为index的元素
indexOf(x):返回线性表中第一次出现的x的索引。若x不存在,则返回-1
erase(index):删除表中索引为index的元素 索引大于index的元素其索引-1
insert(index,x):把x插入线性表中索引为index的位置,索引大于等于index的元素其索引加1
output():从左到右输出表元素
}
用C++的抽象类来表示linearList:
//========================线性表的抽象描述========================
template <typename T>
class myLinearList {
public:
virtual ~myLinearList(){ }
virtual bool empty()const = 0;//是否为空线性表
virtual size_t get_size()const = 0;//返回线性表的元素个数
virtual T get_element(size_t index)const = 0;//返回索引处的元素值
virtual size_t index_of(const T& element)const = 0;//返回该元素第一次出现的索引
virtual void insert(const T&,size_t index) = 0;//在指定索引处位置插入元素
virtual void erase(size_t index) = 0;//删除指定索引位置的元素
virtual void output(std::ostream& os=cout) const= 0;//遍历输出线性表
};
此章我们用数组描述(array representation)来表示线性表,用数组/vector来存储线性表的元素。所有元素存储在连续的内存区域中。
用线性表的数组表示:
#include <iostream>
#include <algorithm>
#include <string>
#include <iterator>
#include <sstream>
#include <vector>
using std::cout; using std::cerr; using std::cin; using std::ends; using std::endl;
using std::string;
using std::vector;
//========================自定义的参数异常类==========================
class illegalParameterValue {
public:
illegalParameterValue() :message("Illegal parameter value!"){
}
illegalParameterValue(const string& _message):message(_message){
}
string what() const{
return message; }
void output()const {
cout << message << endl; }
private:
string message;
};
//========================数组线性表的复制、变长时用到的工具模板函数========================
template <typename T>
void change_array_length1D(T*& a,size_t oldLength,size_t newLength) {
if (newLength < 0) throw illegalParameterValue("new length must be >=0");
T* new_arr = new T[newLength];
size_t new_size = std::min(oldLength, newLength);
for (size_t i = 0; i < new_size; ++i) {
//拷贝数据
new_arr[i] = a[i];
}
//std::copy(a, a + new_size,new_arr);//使用STL::copy来拷贝数据
delete[] a;//释放原内存
a = new_arr;//更新指针
}
//========================自实现类arrayList的双向迭代器========================
//五类迭代器,所有迭代器都支持==、!=和解引用*
//输入迭代器:只读 不写(*解引用只会出现在赋值运算符=的右侧) 单遍扫描 只能递增
//输出迭代器:只写 不读(*解引用只会出现在赋值运算符=的左侧) 单遍扫描 只能递增(向一个已经解引用的输出迭代器赋值,就是将值写入它所指向的元素)
//前向迭代器:可读写 多遍扫描 只能递增
//双向迭代器:可读写 多遍扫描 可递增递减
//随机迭代器:可读写 多遍扫描 支持全部迭代器运算
//符合STL及泛型标准的各类型迭代器实现应该继承自std::iterator接口:https://zh.cppreference.com/w/cpp/iterator/iterator
//自实现类arrayList的简易迭代器
template <typename T>
class my_iterator {
public:
//公有成员
typedef std::bidirectional_iterator_tag iterator_category;//迭代器类型标签
typedef T value_type;//值类型
typedef std::ptrdiff_t difference_type;//标识迭代器之间的距离 C++17 弃用
typedef T* pointer;//指向被迭代的类型(T)的指针
typedef T& reference;//被迭代类型(T)的引用
//构造函数
my_iterator(T* _ptr = 0) :position(_ptr) {
}
//解引用操作
T operator*() const {
return *position; }
T* operator->() const {
return &(*position); }
//递增递减
my_iterator& operator++() {
++position; return *this; }
my_iterator& operator--() {
--position; return *this; }
my_iterator operator++(int) {
my_iterator ret = *this; ++(*this); return ret; }
my_iterator operator--(int) {
my_iterator ret = *this; --(*this); return ret; }
//相等
bool operator==(const my_iterator& rhs)const {
return position == rhs.position; }
bool operator!=(const my_iterator& rhs)const {
return position != rhs.position; }
protected:
T* position;//指向元素的指针
};
//========================线性表的抽象描述========================
template <typename T>
class myLinearList {
public:
myLinearList() = default;
virtual ~myLinearList(){
}
virtual bool empty()const = 0;//是否为空线性表
virtual size_t get_size()const = 0;//返回线性表的元素个数
virtual size_t g