線性表是一種典型的線性結構。其基本特點是線性表中的數據元素是有序且是有限的。在這種結構中:
① 存在一個唯一的被稱為“第一個”的數據元素;
② 存在一個唯一的被稱為“最後一個”的數據元素;
③ 除第一個元素外,每個元素均有唯一一個直接前驅;
④ 除最後一個元素外,每個元素均有唯一一個直接後繼。
線性表(Linear List) :是由n(n≧0)個數據元素(結點)a1,a2, …an組成的有限序列。該序列中的所有結點具有相同的數據類型。 線性表中的數據元素 ai 所代表的具體含義隨具體應用的不同而不同。在線性表的定義中,只不過是一個抽象的表示符號,它可以是一個數字、一個字符串或一個記錄。
◆ 線性表中的結點可以是單值元素(每個元素只有一個數據項) 。
例1: 26個英文字母組成的字母表:
(A,B,C、…、Z)
例2 : 某校從1978年到1983年各種型號的計算機擁有量的變化情況,用線性表的形式給出:
(6,17,28,50,92,188)
例3 : 一副撲克的點數
(2,3,4,…,J,Q,K,A)
線性表中的數據元素是各種各樣的,但同一線性表必定具有相同的特性,即屬同一數據對象。相鄰數據元素之間存在序偶關系。將非空的線性表記作:
(a1,a2,…an)
a1 (無前驅)稱為線性表的第一個(首)結點,
an (無後繼)稱為線性表的最後一個(尾)結點。
當n=0時,稱為空表。
a1,a2,…ai-1都是ai(2 ≤ i ≤ n)的前驅,其中ai-1是ai的直接前驅;
ai+1,ai+2,…an都是ai(1≤i ≤ n-1)的後繼,其中ai+1是ai的直接後繼。
##
順序存儲 :把線性表的結點按邏輯順序依次存放在一組地址連續的存儲單元裡。用這種方法存儲的線性表簡稱順序表。
順序存儲的線性表的特點:
◆ 線性表的邏輯順序與物理順序一致;
◆ 數據元素之間的關系是以元素在計算機內“物理位置相鄰”來體現。
在高級語言(如C語言)環境下:數組具有隨機存取的特性,因此,借助數組來描述順序表。
除了用數組來存儲線性表的元素之外,順序表還應該有表示線性表的長度屬性,所以用結構類型來定義順序表類型。
#define OK 1
#define ERROR -1
#define MAX_SIZE 100
typedef int Status ;
typedef int ElemType ;
typedef struct sqlist
{ ElemType *Elem_array ;
int length;
} SqList ;
順序存儲結構中,很容易實現線性表的一些操作:初始化、賦值、查找、修改、插入、刪除、求長度等。
以下將對幾種主要的操作進行討論
Status Init_SqList( SqList *L ) //新建一張名為L的空表
{ L->elem_array=( ElemType * )malloc(MAX_SIZE*sizeof( ElemType ) ) ;
if ( !L -> elem_array ) return ERROR ; //如果返回空指針,則表示分配失敗
else { L->length= 0 ; return OK ; }
在線性表 L= (a1,…a i-1,ai, ai+1,…,an) 中的第i(1≦i≦n+1)個位置上插入一個新結點e,使其成為線性表: L=(a1,…a i-1,e,ai,ai+1,…,an)
若i=n+1,則表示將元素插入到表最後位置
實現步驟
(1) 將線性表L中的第i個至第n個結點後移一個位置。
(2) 將結點e插入到結點ai-1之後。
(3) 線性表長度加1。
插入算法思想
若i=n+1,則將x插入到表尾;
若表長度n<0或插入位置不適當,則輸出錯誤信息,並返回-1;
當1<=i<=n時,則從表尾開始到第i個依次向後移動一個位置(共需移動n-i+1個數據元素。
最後將e存入L->Elem_array[i]中,表長n增1插入成功,函數返回值為1。
算法實現
Status Insert_SqList(Sqlist *L,int i ,ElemType e)
{ int j ;
if ( i<1||i>L->length+1) return ERROR ;
if (L->length>=MAX_SIZE)
{ printf(“線性表溢出!\n”); return ERROR ; }
for ( j = L->length-1; j >=i-1; --j )
L->Elem_array[j+1]=L->Elem_array[j];
/* i-1位置以後的所有結點後移 */
L->Elem_array[ i-1 ]=e; /* 在第i個位置插入結點 */
L->length++ ;
return OK ;
}
在線性表L中的第i個位置插入新結點,其時間主要耗費在表中結點的移動操作上,因此,可用結點的移動來估計算法的時間復雜度。
若i=1,需移動全部n個結點(最壞:O(n))
若i=n+1(在表尾插入),無需用移動結點。(最好O(1))
設在線性表L中的第i個元素之前插入結點的概率為Pi,不失一般性,設插入各個位置的概率相等,則Pi=1/(n+1),而插入時移動結點的次數為n-i+1。
在線性表 L=(a1,…a i-1,ai, ai+1,…,an) 中刪除結點ai(1≦i≦n),使其成為線性表: L= (a1,…ai-1,ai+1,…,an)
實現步驟
(1) 將線性表L中的第i+1個至第n個結點依次向前移動一個位置。
(2) 線性表長度減1。
刪除算法思想
若表長度n<=0或刪除位置不適當,則輸出錯誤信息,並返回-1;
若i=n,只需刪除尾結點,不用移動結點;
當1<=i
刪除算法實現
ElemType Delete_SqList(Sqlist *L,int i)
{ int k ; ElemType x ;
if (L->length==0)
{ printf(“線性表L為空!\n”); return ERROR; }
else if ( i<1||i>L->length )
{ printf(“要刪除的數據元素不存在!\n”) ;
return ERROR ; }
else { x=L->Elem_array[i-1] ; /*保存第i個結點的值*/
for ( k=i ; k<=L->length-1 ; k++)
L->Elem_array[k-1]=L->Elem_array[k];
/* i+1位置以後的所有結點前移 */
L->length--; return (x);
}
}
在線性表 L= (a1,a2,…,an) 中刪除值為x的第一個結點。
實現步驟
(1) 在線性表L中查找值為x的第一個數據元素。
(2) 將從找到的位置至最後一個結點依次向前移動一個位置。
(3) 線性表長度減1。
算法描述
Status Locate_Delete_SqList(Sqlist *L,ElemType x)
/* 刪除線性表L中值為x的第一個結點 */
{ int i=0 , k ;
while (i<L->length) /*查找值為x的第一個結點*/
{ if (L->Elem_array[i]!=x ) i++ ;
else // 找到!
{ for ( k=i+1; k< L->length; k++)
L->Elem_array[k-1]=L->Elem_array[k];
L->length--; break ; //跳出while循環
}
}
if (i>L->length)
{ printf(“要刪除的數據元素不存在!\n”) ;
return ERROR ; }
return OK;
}
時間主要耗費在數據元素的比較和移動操作上。
首先,在線性表L中查找值為x的結點是否存在;
其次,若值為x的結點存在,且在線性表L中的位置為i ,則在線性表L中刪除第i個元素。
設在線性表L刪除數據元素概率為Pi,不失一般性,設各個位置是等概率,則Pi=1/n。
◆ 比較的平均次數: Ecompare=∑pi*i (1≦i≦n)
∴ Ecompare=(n+1)/2 。
◆ 刪除時平均移動次數:Edelete=∑pi*(n-i) (1≦i≦n)
∴ Edelete=(n-1)/2 。
平均時間復雜度:Ecompare+Edelete=n ,即為O(n)