线性表--数组/vector描述

一个线性表(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 
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 
#include 
#include 
#include 
#include 
#include 

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 get_capacity()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;//遍历输出线性表
};

//========================数组描述的线性表========================
//.h
template <typename T>
class myArrayList :public myLinearList<T> {
public:
	myArrayList(size_t _capacity = 10);//默认容器容量为10
	myArrayList(const myArrayList& mal);//拷贝构造函数
	myArrayList(myArrayList&& mal);//移动构造函数
	~myArrayList() { delete[] arr; }

	bool empty()const { return size == 0; }
	size_t get_size()const { return size; }
	size_t get_capacity()const { return capacity; }
	T get_element(size_t index)const;
	size_t index_of(const T& element)const;
	void insert(const T& element, size_t index);
	void erase(size_t index);
	void output(std::ostream& os = cout)const;
	void resize(size_t newsize);
	void set(size_t _index,const T& _element);
	void clear();

	my_iterator<T> begin()const { return my_iterator<T>(arr); }
	my_iterator<T> end()const { return my_iterator<T>(arr + size); }

protected:
	T* arr;//存储元素的一维数组
	size_t size;//数组元素的数目
	size_t capacity;//数组的容量

	void check_index(size_t index) const;//arrayList检查索引的私有工具函数
};

//.cpp
template <typename T>
myArrayList<T>::myArrayList(size_t _capacity) {
	if (_capacity < 1) {//初始容量必须大于等于1
		std::ostringstream oss;
		oss << "Initial capacity of array list must be > 0";
		throw illegalParameterValue(oss.str());
	}
	capacity = _capacity;
	arr = new T[capacity];
	size = 0;
}

template <typename T>
myArrayList<T>::myArrayList(const myArrayList& mal) {
	size = mal.size;
	capacity = mal.capacity;
	arr = new T[capacity];
	for (size_t i = 0; i < size; ++i) {
		arr[i] = mal.arr[i];
	}
	//std::copy(mal.arr,mal.arr+size,arr);//利用std::来拷贝
	return *this;
}

template <typename T>
myArrayList<T>::myArrayList(myArrayList&& mal):size(mal.size),capacity(mal.capacity),arr(mal.arr) {//移动构造函数
	//直接接管资源 并将被移动对象置为可析构状态
	mal.size = mal.capacity = 0;
	mal.arr = nullptr;
}

template <typename T>
void myArrayList<T>::output(std::ostream& os) const {
	if (size > 0)
		std::copy(arr, arr + size, std::ostream_iterator<T>(os, " "));//ostream_iterator 一般搭配泛型算法使用
	else cout << "empty array list!" << endl;;
}

template<typename T>
std::ostream& operator<<(std::ostream& os, const myArrayList<T>& mal) {
	mal.output(os);
	return os;
}

template <typename T>
void myArrayList<T>::check_index(size_t index) const {
	if (index < 0 || index >= size) {
		std::ostringstream oss;
		oss << "index must  be >=0 and  << index << "is illegal" << endl;
		throw illegalParameterValue(oss.str());
	}
}

template <typename T>
T myArrayList<T>::get_element(size_t index) const {
	check_index(index);
	return arr[index];
}

template <typename T>
size_t myArrayList<T>::index_of(const T& element) const {
	size_t pos;
	pos = std::find(arr, arr + size, element) - arr;//利用std::find查找
	if (pos == size)
		return -1;
	return pos;
}

template <typename T>
void myArrayList<T>::erase(size_t index) {
	check_index(index);
	//std::copy(arr+index+1,arr+size,arr+index);//利用std::copy拷贝
	for (size_t i = index + 1; i < size; ++i) {
		arr[i - 1] = arr[i];
	}
	arr[--size].~T();//调用析构函数对最后尾元素析构
}

template <typename T>
void myArrayList<T>::insert(const T& element, size_t index) {
	if (index < 0 || index > size) {
		std::ostringstream oss;
		oss << "insert index must  be >=0 and <=size, while" << index << "is illegal" << endl;
		throw illegalParameterValue(oss.str());
	}
	if (size == capacity) {//容器已满
		change_array_length1D(arr, capacity, 2 * capacity);
		capacity *= 2;
	}
	//元素右移一个单位
	size_t i;
	for (i = size; i > index; --i) {
		arr[i] = arr[i - 1];
	}
	//std::copy_backward(arr+index,arr+size,arr+size+1);//利用std::backward把元素右移一个单位,可能的实现见后面
	arr[i] = element;
	++size;
}

template <typename T>
void myArrayList<T>::resize(size_t newsize) {
	if (newsize < 0) throw illegalParameterValue("new size must be >=0!");
	if (newsize < size) {//小于当前size则进行缩减
		while (size > newsize) {
			arr[--size].~T();
		}
	}
	else if (newsize<=capacity) {
		while (size < newsize) {
			arr[size++] = T();//以T默认构造函数填充
		}
	}
	else{//需要分配新空间
		change_array_length1D(arr, capacity, 2 * newsize);//得到新的大空间的数组
		while (size < newsize) {
			arr[size++] = T();
		}
		capacity = 2*newsize;
	}
}

template <typename T>
void myArrayList<T>::set(size_t _index,const T& _element) {
	check_index(_index);
	arr[_index] = _element;
}

template <typename T>
void myArrayList<T>::clear() {
	while (size>0) {
		arr[--size].~T();
	}
}

//========================std::copy_backward可能的实现========================
//std::copy_backward(start,end,dest) 
//复制[start,end)的元素到终于dest的位置即[dest-(end-start),dest) 逆序拷贝(首先拷贝end-1的元素到dest-1)
template <typename BidirIter1,typename BidirIter2>//双向迭代器Bidirectional iterator
BidirIter2 my_copy_backward(BidirIter1 begin,BidirIter1 end,BidirIter2 dest_end) {
	while (end!=begin) {
		*(--dest_end) = *(--end);
	}
	return dest_end;
}


//test
int main() {
	//test for i/ostream_iter
	//std::istringstream str("0.05");
	//std::istream_iterator initer(str);//可以在输入流中将string转为double 等价于std::atoi(str);
	//cout << *initer + *initer << endl;

	//test for my_copy_backward
	//vector vec{ 0,1,2,3,4,5,6,7,8,9};
	//for (const auto& i : vec) cout << i << ends;
	//cout << endl;
	std::copy_backward(vec.begin(),vec.begin()+4,vec.begin()+10);
	//my_copy_backward(vec.begin(),vec.begin()+4,vec.begin()+10);
	//for (const auto& i : vec) cout << i << ends;

	//test for my_iterator
	//int num []{ 0,1,2,3,4,5,6,7,8,9 };
	//my_iterator myIter(num);
	//my_iterator myEndIter(num+10);
	//for (; myIter != myEndIter;++myIter) {//++和!=操作
	//	cout << *myIter << ends;//*操作
	//}

	//test for myArraList
	myArrayList<int> mylist;
	cout << "capacity:" << mylist.get_capacity() << ends << "size:" << mylist.get_size() << endl;
	if(mylist.empty())
		mylist.output();
	mylist.insert(20,0);
	mylist.insert(21,1);
	mylist.insert(22,2);
	mylist.insert(23,3);
	if (!mylist.empty())
		cout << mylist;
	cout << endl;
	cout << "element at index 3:"<<mylist.get_element(3) << endl;
	mylist.erase(mylist.index_of(22));	
	cout << "erased 22" << endl;
	cout << "now 23 is at index:" << mylist.index_of(23) << endl;
	if (mylist.index_of(22) == -1) cout << "22 is not in the array list !" << endl;
	for (my_iterator<int> myIter = mylist.begin();myIter!=mylist.end(); ++myIter) {
		cout << *myIter << ends;
	}
	return 0;
}

基于vector的线性表描述,与数组描述相差无几:

//========================基于vector的线性表描述myVectorList========================
//.h
template <typename T>
class myVectorList :public myLinearList<T> {
public:
	myVectorList(size_t _capacity = 10);
	myVectorList(const myVectorList& mvl);
	~myVectorList() { delete v_ptr; }
	
	bool empty()const { return v_ptr->empty(); }
	size_t get_size()const { return v_ptr->size(); }
	size_t get_capacity()const { return v_ptr->capacity(); }
	T get_element(size_t index)const;
	size_t index_of(const T& element)const;
	void insert(const T& element,size_t index);
	void erase(size_t index);
	void output(std::ostream& os=cout)const;
	typename vector<T>::iterator begin()const { return v_ptr->begin(); }
	typename vector<T>::iterator end()const { return v_ptr->end(); }
protected:
	void check_index(size_t index) const;
	vector<T>* v_ptr;//存储线性表元素的向量
};
//.cpp
template <typename T>
myVectorList<T>::myVectorList(size_t _capacity){
	if (_capacity < 1) {
		std::ostringstream oss;
		oss << "initial capacity must be >=1, while given is: " << _capacity;
		throw illegalParameterValue(oss.str());
	}
	v_ptr = new vector<T>(_capacity);
}

template <typename T>
myVectorList<T>::myVectorList(const myVectorList& mvl):v_ptr(new vector<T>(*mvl.v_ptr)) {
}

template <typename T>
void myVectorList<T>::check_index(size_t index) const {
	if (index >= v_ptr->size() || index < 0) {
		std::ostringstream oss;
		oss << "index must  be >=0 and  << index << "is illegal" << endl;
		throw illegalParameterValue(oss.str());
	}
}

template <typename T>
T myVectorList<T>::get_element(size_t index)const {
	check_index(index);
	return v_ptr->at(index);
}

template <typename T>
size_t myVectorList<T>::index_of(const T& element)const {
	size_t pos = std::find(v_ptr->begin(),v_ptr->end(),element) - v_ptr->begin();
	if (pos == v_ptr->size()) return -1;
	return pos;
}

template <typename T>
void myVectorList<T>::erase(size_t index) {
	check_index(index);
	v_ptr->erase(v_ptr->begin()+index);//vector::erase(vector::iterator)
}

template <typename T>
void myVectorList<T>::insert(const T& element,size_t index) {
	if (index > v_ptr->size() || index < 0) {
		std::ostringstream oss;
		oss << "index must  be >=0 and <=size, while" << index << "is illegal" << endl;
		throw illegalParameterValue(oss.str());
	}
	v_ptr->insert(v_ptr->begin()+index,element);//vector::insert(itertor,value)
}

template <typename T>
void myVectorList<T>::output(std::ostream& os) const{
	if (v_ptr->size() > 0) {
		std::copy(v_ptr->begin(),v_ptr->end(),std::ostream_iterator<T>(os," "));
	}
	else *std::ostream_iterator<string>(os) = "empty vector list!";
}
template <typename T>
std::ostream& operator<<(std::ostream& os,const myVectorList<T>& mvl) {
	mvl.output(os);
	return os;
}
//test
int main() {
	myVectorList<int> mylist;
	cout << "capacity:" << mylist.get_capacity() << ends << "size:" << mylist.get_size() << endl;
	if (mylist.empty())
		mylist.output();
	mylist.insert(20, 0);
	mylist.insert(21, 1);
	mylist.insert(22, 2);
	mylist.insert(23, 3);
	if (!mylist.empty())
		cout << mylist;
	cout << endl;
	cout << "element at index 3:" << mylist.get_element(3) << endl;
	mylist.erase(mylist.index_of(22));
	cout << "erased 22" << endl;
	cout << "now 23 is at index:" << mylist.index_of(23) << endl;
	if (mylist.index_of(22) == -1) cout << "22 is not in the array list !" << endl;
	for (auto myIter = mylist.begin(); myIter != mylist.end(); ++myIter) {
		cout << *myIter << ends;
	}
	return 0;
}

你可能感兴趣的:(数据结构,算法与应用)