C++語言實現順序表

C++語言實現順序表

順序表的定義及其特點

順序表的定義是:把線性表中的所有表項按照其邏輯順序依次存儲到從計算機存儲中指定存儲位置開始的一塊連續的存儲空間中。 這樣,線性表中第一個表項的存儲位置就是被指定的存儲位置,第i個表項(2\leq i \leqn)的存儲位置緊接在第i一1個表項的存儲位置的後面。假設順序表中每個表項的數據類型爲T,則每個表項所佔用存儲空間的大小(即字節數)大小相同,均爲 sizeof(T),整個順序表所佔用存儲空間的大小爲n×\times sizeof(T),其中n表示線性表的長度。

順序表的特點是:

(1)在順序表中,各個表項的邏輯順序與其存放的物理順序一致,即第i個表項存儲於
第i個物理位置(1\leq i \leqn).
(2)對順序表中所有表項,既可以進行順序訪問,也可以進行隨機訪問。 也就是說,既可以從表的第一個表項開始逐個訪問表項,也可以按照表項的序號(亦稱爲下標)直接訪問表項。

順序表類定義及其主要操作

順序表的類聲明
class SeqList
{
	private:
		T *data;//存放數據的動態數組
		int maxSize;//最大可容納表項的項數
		int last; //當前已存表項的最後位置(從0開始)
		void reSize(int newSize);	//改變數組空間大小
		
	public:
		SeqList(int sz);          //構造函數
		SeqList(SeqList<T>& L);	           //複製構造函數
		~SeqList() {delete[ ] data;}	        //析構函數
		int Size(){//求表最大容量
			return maxSize;
			}	 
		int Length() {//計算表長度
			return last+1;
			}        
		int Search(T x);//搜索x在表中位置,函數返回表項序號	
		int Locate(int i);//定位第i個表項,函數返回表項序號
		bool Insert(int i, T& x);//插入x在第i個表項之後
		bool Remove(int i, T& x);//刪除第i個表項之後,通過x返回表項的值
		bool GetData(int i,T& x);//取第i個表項的值,以x引用返回
		bool SetData(int i,T& x);//用x修改第i個表項的值
		bool IsEmpty(){//判斷表是否空否,是返回true,否返回false
			return (last==-1) ? true : false;
		}
		bool IsFull(){//判讀表是否滿否,是返回true,否返回false
			return (last = maxSize - 1) ? true : false;
		}
		void input();//輸入數據
		void output();//打印數據
};

構造函數和複製構造函數
template <class T>
inline SeqList<T>::SeqList(int sz)
{
	if (sz > 0) {
		maxSize = sz;  last = -1;
		data = new T[maxSize];	   //創建表存儲數組
		if (data == NULL)		   //動態分配失敗
		{ 
			cout<<"儲存分配錯誤!"<<endl;
		}
	}
}
template <class T>
inline SeqList<T>::SeqList(SeqList<T>& L)
{
	//複製構造函數,用參數表中給出的已有順序表初始化新建的順序表
	maxSize = L.Size();
	last = L.Length()-1;
	T value;
	data = new T[maxSize];//創建順序表儲存數組
	if(data == NULL){
		cout<<"動態分配錯誤!"<<endl;
	}
	for(int i =1;i<=last-1;i++){
		L.GetData(i, value);
		data[i-1] = value;
	}
	
}

調整順序表空間大小
template <class T>
inline void SeqList<T>::reSize(int newSize){
	//私有函數,擴充順序表的儲存數組空間的大小,新數組的元素個數爲newSize.
	if(newSize <= 0){
		cout<<"無效數組的大小!"<<endl;
	}
	if(newSize != maxSize){
		T *newarray = new T[newSize];
		if(newarray == NULL){
			cout<<"儲存分配錯誤!"<<endl;
		}
		int n = last+1;
		T *srcptr = data;//源數組的首地址
		T *desptr = newarray;//目的數組的首地址
		while(n--){//複製
			*desptr++ = *srcptr++;
		}
		delete []data;//刪除老數組
		data = newarray;
		maxSize = newSize;//複製新數組
	}
}

搜索和定位操作
template <class T>
inline int SeqList<T>::Search(T x)
{
	//搜索函數:在表中順序搜索與給定值x匹配的表項,找到則函數返回該表項是第幾個元素
	//否則返回0,表示搜索失敗
	for(int i=0;i<=last;i++){
		if(data[i] == x)
		return i+1;
	}
	return 0;
}
template <class T>
inline int SeqList<T>::Locate(int i)
{
	//定位函數:返回第i(1<=i<=lat+1)個表項的位置,否則函數返回0,表示定位失敗
	if(i>=1 && i<last+1){
		return i;
	}
	else return 0;
}

插入與刪除操作
template <class T>
inline bool SeqList<T>::Insert(int i, T& x)//插入x在第i個表項之後
{
	//將新元素x插入到第i(0<=i<=last+1)個表項之後。函數返回插入成功的信息,若插入成功返回true,否則返回false.
	//i=0時虛擬的,實際上是插入到第1個元素的位置。
	if(last == maxSize - 1){
		return false;//表滿,不能插入
	}
	if(i<0 || i > last+1)
	{
		return false;//參數i不合理,不能插入
	}
	for(int j=last;j>=i;j--)
	{
		data[j+1]=data[j];//一次後移,空出第i號位置
	}
	data[i] = x;//插入
	last++;//最後位置加一
	return true;
}
template <class T>
inline bool SeqList<T>::Remove(int i, T& x)//刪除第i個表項之後,通過x返回表項的值
{
	//從表中刪除第i(0<=i<=last+1)個表項,通過引用型參數x返回刪除的元素值。函數返回刪除成功的信息,刪除成功返回true,刪除失敗返回false
	if(last == -1){
		return false;//表空,不能刪除
	}
	if(i<1 || i>last+1){
		return false;//參數i不合理,不能刪除
	}
	x=data[i];//儲存刪除的元素
	for(int j=i;j<=last;j++)
	{
		data[j-1] = data[j];//依次前移,填補
	}
	last--;//最後位置減一
	return true;
}

順序表的性能分析

順序表所有操作的實現中,最複雜、最耗時的就是搜索、插入和刪除運算的實現代碼。分析順序表的性能,主要是分析這3個操作的實現代碼的時間複雜性。
int search(T& x)是順序表的順序搜索算法。 其主要思想是:

從表的開始位置起,根據給定值x,逐個與表中各表項的值進行比較。 若給定值與某個表項的值相等,則算法報告搜索成功的信息並返回該表項的位置;若查遍表中所有的表項,沒有任何一個表項滿足要求,則算法報告搜索不成功的信息並返回0(必要的話,可改一下算法,返回新表項應插人的位置)。

搜索算法的時間代價用數據比較次數來衡量。 在搜索成功的情形下,順序搜索的數據比較次數可做如下分析。 若要找的正好是表中第1個表項,數據比較次數爲1,這是最好情況;若要找的是表中最後的第n個表項,數據比較次數爲n(設表的長度爲n),這是最壞的情況 。若要計算平均數據比較次數,需要考慮各個表項的搜索概率p及找到該表項時的數據比較次數pip_i.搜索的平均數據比較次數ACN(average comparing number)爲
ACN=i=1npi×ci\sum_{i=1}^n {p_i}\times c_i

計算平均數據比較次數是爲了瞭解對錶操作的整體性能。若考慮相等概率的情形。搜索各表項的可能性相同,有p1p_1=p2p_2=…=pnp_n=1n\frac1 n,且搜索第1個表項的數據比較次數爲1,搜計算平均值是爲了解算法對錶操作的整體性能。 若僅考慮相等概率的情形。搜索各表索第2個表項的數據比較次數爲2,搜索第i號表項的數據比較次數爲i,則
ACN=1ni=1ni=1n(1+2+3+...+n)==1+n2\frac1 n\sum_{i=1}^ni=\frac1 n(1+2+3+...+n)==\frac{1+n} 2
即平均要比較n+12\frac{n+1} 2個表項。

分析順序表的插入和刪除的時間代價主要看循環內的數據移動次數
在將新表項插入到第i個表項(0\leq i \leqn)後面時,必須從後向前循環,逐個向後移動n-i個表項。 因此,最好的情形是在第n個表項後追加新表項,移動表項個數爲0;最差情形是在第1個表項位置插人新表項(視爲在第0個表項後面插入),移動表項個數爲n;平均數據移動次數AMN(average moving number)在各表項插入概率相等時爲
AMN=1n+1i=0n(ni)=1n+1n(n+1)2=n2\frac1 {n+1}\sum_{i=0}^n{(n-i)}=\frac1 {n+1}\frac{n (n+1)} 2=\frac n 2
即就整體性能來說,在插入時有n+1個插入位置,平均移動n2\frac n 2個表項!

在刪除第i個表項(1\leq i \leqn)時,必須從前向後循環,逐個移動n一i個表項。 因此,最好的情形是刪去最後的第n個表項,移動表項個數爲0;最差情形是刪去第1個表項,移動項個數爲n-1;平均數據移動次數AMN在各表項刪除概率相等時爲
AMN=1ni=1n(ni)=1nn(n1)2=n12\frac1 n\sum_{i=1}^n{(n-i)}=\frac1 {n}\frac{n (n-1)} 2=\frac {n-1} 2
就整體性能來說,在刪除時有n個刪除位置,平均移動(n-1)/2個表項。

以上是C++順序表使用過程中最常用的主要操作,相關完整代碼已經push到GitHub,需要的小夥伴自行clone,如果覺得還不錯的話,歡迎Star,這裏是傳送門C++順序表,除此之外,想要了解更多的C,C++,Java,Python等相關知識的童鞋,歡迎來我的博客相逢的博客,我們一起討論!接下來我會更新C語言鏈式結構實現線性表,敬請期待!

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