Linear table of C++ data structure (custom array)

First use the abstract class LinearList to define a linear list

template<class T>
class LinearList {
    
    
public:
	virtual ~LinearList() {
    
    };

	virtual bool empty()const = 0;
	virtual int size()const = 0;
	virtual T &Getelement(int index)const = 0;//返回index下标处元素
	virtual int ElementPos(const T &Element)const = 0;//返回Element第一次出现位置
	virtual void earse(int Index) = 0;//删除Index下标处元素
	virtual void insert(int Index, const T &Element) = 0;//插入Element至Index下标处
	virtual void ouput(ostream &out)const = 0;//输出流对象
};

For convenience, customize an exception class to throw subscript out-of-bounds exceptions when necessary

class illegalIndexValue {
    
    
public:
	illegalIndexValue() : message("Illegal index value") {
    
    }

private:
	string message;
};

Next is a custom array class ArrayList, inherited from LinearList, adding necessary functions on the basis of implementing virtual functions.

template<class T>
class ArrayList :public LinearList<T> {
    
    
public:
	ArrayList(int x = 10);
	ArrayList(const ArrayList &p);//复制构造函数
	~ArrayList();

	bool empty()const;
	int size()const;
	T &Getelement(int Index);//返回index下标处元素
	int ElementPos(const T &Element);//返回Element第一次出现位置
	void earse(int Index);//删除Index下标处元素
	void insert(int Index, const T &Element);//插入Element至Index下标处
	void ouput(ostream &out)const;//输出流对象

	int Getcapacity()const;//返回数组容量

	void ChangeLength(int OldL, int NewL);//改变数组长度

	friend ostream &operator<<(ostream &out, const ArrayList<T>&x);

	void CheckIndex(int index)const;//检查check是否越界
protected:

	T *element;//存储一维数组
	int ArrayLength;//一维数组容量
	int ListSize;//当前元素个数
};

The first is the function realization of the constructor, copy constructor and destructor. In the constructor, dynamic allocation is performed on the basis of test data and rationality. In the copy constructor, a deep copy assignment is first required. Release the dynamically allocated memory in the destructor.

template<class T>
ArrayList<T>::ArrayList(int x) {
    
    
	if (x < 0) {
    
    
		throw illegalIndexValue();
	}

	ArrayLength = x;
	ListSize = 0;
	element = new T[ArrayLength];
}

template<class T>
ArrayList<T>::ArrayList(const ArrayList &p) {
    
    
	ArrayLength = p.ArrayLength;
	ListSize = p.ListSize;
	//深拷贝数组元素
	element = new T[ArrayLength];
	copy(p.element, p.element + ArrayLength, element);
}

template<class T>
ArrayList<T>::~ArrayList() {
    
    
	delete[]element;
}

In a one-dimensional array, we often need to change the length of the array. At this time, we need to construct a new array first, then use the copy function to copy the elements, and finally release the old array memory.

template<class T>
void ArrayList<T>::ChangeLength(int OldL, int NewL) {
    
    

	T *temp = new T[NewL];
	int Number = min(OldL, NewL);
	copy(element, element + Number, temp);//将数组成员赋值到新数组中去
	delete[]element;
	element = temp;
}

Next are the two key functions earse() and insert(). The idea of ​​earse() is to delete the element whose index is index, then move the element of index+1, index+2,..., ListSize-1 one position to the left , And release the last element. The idea of ​​insert() is to first check whether the length of the array meets the requirements. Then use copy_backward() to move the element from index index to ListSize-1 to the right, and insert the element with index index.

template<class T>
void ArrayList<T>::earse(int Index) {
    
    
	CheckIndex(Index);
	copy(element + Index + 1, element + ListSize, element + Index);
	element[--ListSize].~T();

}

template<class T>
void ArrayList<T>::insert(int Index, const T &Element) {
    
    
	CheckIndex(Index);
	if (ListSize == ArrayLength) {
    
    
		ChangeLength(ArrayLength, ArrayLength + 1);
	}
	copy_backward(element + Index, element + ListSize, element + ListSize + 1);//第三个参数是目的序列的结束迭代器
	element[Index] = Element;
}

Finally, it is the preparation of other functions, so no explanation is needed, and the code is directly written.

template<class T>
void ArrayList<T>::CheckIndex(int index)const
{
    
    
	if (index < 0 || index >= ListSize) {
    
    
		throw illegalIndexValue();
	}
}

template<class T>
bool ArrayList<T>::empty()const {
    
    
	return ListSize == 0;
}

template<class T>
int ArrayList<T>::size()const {
    
    
	return ListSize;
}

template<class T>
T &ArrayList<T>::Getelement(int Index) {
    
    
	CheckIndex(Index);
	return element[Index];
}

template<class T>
int ArrayList<T>::ElementPos(const T &Element) {
    
    
	int Index = (int)(find(element, element + ListSize, Element) - element);

	if (Index == ListSize)
		return -1;
	else
		return Index;
}

template<class T>
int ArrayList<T>::Getcapacity()const {
    
    
	return ArrayLength;
}

template<class	T>
void ArrayList<T>::ouput(ostream &out)const {
    
    
	copy(element, element + ListSize, ostream_iterator<T>(cout, " "));
}

template<class T>
ostream &operator<<(ostream &out, const ArrayList<T>&x) {
    
    
	x.ouput(out);
	return out;
}

Guess you like

Origin blog.csdn.net/GGGGG1233/article/details/114695863