數據結構和算法之線性表(C++)

線性表的順序存儲結構的特點是,用物理上的鄰接關係表達邏輯上的前驅和後繼,因此可以通過簡單的公式獲取表中的任意元素的地址,但是在插入和刪除過程中需要移動大量元素,同時對存儲空間的利用不是很合理。接下來我用C++的模板式編程來實現線性表的基本功能

template<typename T>
class Linearlist
{
public:
	Linearlist() {};
	virtual bool Isempty()const { return length; };
	virtual bool Find(int k, T &b)const = 0;
	virtual bool Delete(int k, T &b) = 0;
	virtual bool Insert(int k, const T&b) = 0;
	virtual void Output(ostream &out) const = 0;
	virtual ~Linearlist() {};
private:
	int length;
};

這裏利用了抽象函數來實現線性表和鏈表的一些基本功能,其中判斷是否爲空不是抽象類,因爲判斷是否爲空的實現方式比較類似,通過多態可以實現。其他的爲純虛函數,便於接下來對線性表的表達。

template<typename T>
class LinearListSqu : public Linearlist<T>
{
public:
	LinearListSqu(int Maxlistsize = 10);
	~LinearListSqu() { if (element) { delete[]element; } };
	virtual bool Isempty()const { return length == 0; };
	virtual int Length()const { return length; };
	virtual bool Find(int k, T &b)const;
	virtual bool Delete(int k, T &b);
	virtual bool Insert(int k, const T&b) ;
	virtual void Output(ostream &out) const;
protected:
	int Maxsize;
	T *element;
	int length;
};

這裏是抽象類的繼承,通過使用指針數組的方式來創建一個線性表,同時在結尾需要對指針的釋放,防止內存泄露,其中的思路比較簡單,最後還用到了輸出運算符重載(<<的重載),使其可以輸出對象的元素,簡化了後續的步驟。

class Nomem
{
public:
	Nomem() { cout << "memory is not enough" << endl; };
	~Nomem() {};

private:

};

class OutofBound
{
public:
	OutofBound() { cout << "out of bound"; };
	~OutofBound() {};

private:

};

這裏是檢查函數是否出現異常進行異常處理,採用了防禦式編程的思想

template<typename T>
LinearListSqu<T>::LinearListSqu(int Maxlistsize)
{
	Maxsize = Maxlistsize;
	try
	{
		element = new T[Maxsize];
	}
	catch (...)
	{
		throw Nomem();
	}
	length = 0;
}

template<typename T>
bool LinearListSqu<T>::Find(int k, T &b)const
{
	if (k<1||k>length)
	{
		return false;
	}
	else
	{
		b = element[k - 1];
		return true;
	}
}

template<typename T>
void LinearListSqu<T>::Output(ostream &out) const
{
	for (int i = 0; i < length; i++)
	{
		out << element[i] << " ";
	}
}

template<typename T>
ostream &operator << (ostream &out,LinearListSqu<T>& b)
{
	b.Output(out);
	return out;
}

template<typename T>
bool LinearListSqu<T>::Insert(int k, const T &b)
{
	if (k < 0 || k > length)
	{
		throw OutofBound();
	}
	if (length == Maxsize)
	{
		throw Nomem();
	}
	for (int i = length-1; i >=k; i--)	//第幾個數字減一得到指針的序數,例如 1,2,3,4,5,6  轉化爲指針地址爲0,1,2,3,4,5
	{
		element[i + 1] = element[i];
	}	//最後一個數字減一後從k算起
	element[k] = b;	//在移出來的空位補一個元素
	length++;	//長度加一
	return true;
}

template<typename T>
bool LinearListSqu<T>::Delete(int k, T &b)
{
	if (Find(k ,b))
	{
		for (int i = k; i < length; i++)
		{
			element[i - 1] = element[i];
			length--;
			return true;
		};
	}
	else throw OutofBound();
}

這裏便是對線性表功能的基本實現,具體思路很清晰,大家理解應該沒什麼問題
最後便是主函數的實現,用於測試該線性表的正確性。

int main()
{
	try
	{
		LinearListSqu<int>L (5);
		cout << "length==" << L.Length() << endl;
		cout << "is empty" << L.Isempty() << endl;
		bool ok = false;
		ok = L.Insert(0, 2);
		if (!ok)cout << "ok" << endl;
		L.Insert(1, 6);
		L.Insert(2, 8);
		cout << "List = " << L << endl;
		cout << "Is Empty" << L.Isempty() << endl;
		int z;
		L.Find(1, z);
		cout << "First element is" << z << endl;
		cout << "Length = " << L << endl;
		L.Delete(1, z);
		cout << "Delete element is" << z << endl;
		cout << "List is" << L << endl;
	}
	catch (...)
	{
		cout << "An exception has occured" << endl;
	}
}

這就是該線性表的簡單實現,筆者爲了練習而寫的,如果有不好的地方歡迎大家批評指正。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章