資料結構,資料結構與演算法
線性表
線性表是一種典型的線性結構。其基本特點是線性表中的資料元素是有序且是有限的。在這種結構中:
① 存在一個唯一的被稱為“第一個”的資料元素;
② 存在一個唯一的被稱為“最後一個”的資料元素;
③ 除第一個元素外,每個元素均有唯一一個直接前驅;
④ 除最後一個元素外,每個元素均有唯一一個直接後繼。
線性表(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 100typedef 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 ; //如果返回null 指標,則表示分配失敗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)