1. 程式人生 > >大話資料結構筆記_線性表

大話資料結構筆記_線性表

線性表的定義 :

  簡而言之 : 0 個 或 多個元素(型別相同)的有限序列( 有順序 ) , 第一個元素無前驅 , 最後一個元素無後繼 , 其他元素 與有唯一的前驅 和 唯一的後繼
  數學語言定義 : 若將線性表記為 ( a1 , a2 , ..... , ai - 1 , ai , ai+1 , ... , an) , 則表中 ai-1 領先於 ai , ai 領先於 ai+1
           稱 ai-1 是 ai 的前驅 , ai+1 是 ai 的後繼元素 . 當 i = 1 , 2 ... , n - 1 時候 , ai 有且僅有 一個 直接後
         繼 , 當 i = 2 ,......., n 時候 , ai 有且僅有一個直接的前驅。
  線性表的長度 : 線性表的元素的個數 n( n>=0 ) , 當 n = 0 時候 我們稱之為空表


 

線性表的ADT :

  注意 :  這只是 抽象 層面 來說 , 也就是說實現方式儘管 有 順序表連表等實現方式 , ADT僅僅抽取他們的相同
      處 且 基本具有的操作 , 具體實現時候 , 可以新增Data 資料 , 可以 擴充 操作 或者新增 輔助方法( 抽取
      相同程式碼 )。 對於實際問題中更復雜的操作 , 可以使用ADT中的基本操作來組合完成。

       定義如下:
    

ADT 線形表 ( List ) 
Data : 下一層資料型別 + 描述
線性表的資料物件的序列 {a1,a2,a3,......, an} , 每個元素均為DataType , 其中 , 除了元素 a1 外 , 每一個    
元素都只有唯一的前驅元素 , 除了an外 , 每個元素都只有唯一的後繼元素 。 元素之間的關係是一對一的關 
系。
Operation: 操作 
+ 描述 (規定 : 提前說明 , 我們使用的編號 均從 0 開始 , 操作返回 0 代表成功 , -1 代表失敗) InitList(*L) : 初始化操作 , 給L 指標指向的List型別開闢能容納序列的空間 ListEmpty(L) : 若線性表為空 , 返回true else false ClearList(*L) : 將線效能表清空 GetElem(L , i ,*e) : 將線性表L中的第i個元素通過傳出引數e取出 , 返回值 0 代表的 成功 , -1 代表錯誤 LocateElem(L,e ) : 將線形表L 中查詢 第一個匹配到的e , 成功返回 編號位置 , 失敗返回-1 ListInsert(
*L , i , e) : 線上性表第 i 個元素 的前面 插入一個元素 , 成功返回 0 失敗返回 -1 ListDelete(*L , i ,*e ): 刪除線性表中的第i個位置的元素 , 並用e返回其值 ListLength(L) : 返回線性表中的元素的個數 : endADT

 


線形表的順序儲存結構:

  ADT -> 物理層面 -> 語言實現( C 語言實現):

  指的是使用一段連續的儲存單元依次儲存線性表的資料元素。

   

sqList 結構體 定義在標頭檔案當中:

#ifndef __SEQ_LIST_H
#define __SEQ_LIST_H

#define MAXSIZE 20     /*假設順序表的容量為20*/
#define TRUE     0     /*我們只使用TRUE 和 FALSE 兩個量表示成功和失敗就行了 , 但是注意TRUE是0*/
#define FALSE   -1   
 
typedef int ElemType;  /*假設ElemType 型別為int*/
typedef int BOOL;      /*BOOL 表示兩個量 : TRUE | FALSE */
 
/*結構體的宣告放在*/
typedef struct
{
     ElemType data[MAXSIZE];
     int length;        /*擴充了ATD的DATA,其表示指向序列最後一個元素的下一個位置*/
}sqList;
  
/*函式的宣告放在這個位置 */
extern void InitList(sqList * L);
extern BOOL ListEmpty(sqList L);
extern void ClearList(sqList * L);
extern int LocateElem(sqList L , ElemType e);
extern int  ListLength(sqList L);
extern BOOL ListInsert(sqList * L , int i , ElemType e);
extern BOOL ListDelete(sqList * L , int i , ElemType *e);
extern int GetElem(sqList L , int i  , ElemType * e); 

#endif
sqList 結構體定義 以及 操作介面宣告

sqList 操作定義在 .c 檔案當中 :

/*************************************************
Function: InitList 
Description: 初始化順序表的長度為 0 
Output: *L : 線性表發生變動
Return: 空 TRUE | 非空FALSE (TRUE :0  FALSE:-1)
*************************************************/
void InitList(sqList * L)
{
     L->length = 0;
}

/*************************************************
Function: LisEempty
Description: 返回順序表是否為空 , O(1)
              
              判斷 L->length 是否為0即可
 
Input:       L : 線性表結構 
Return: 空 TRUE | 非空FALSE (TRUE :0  FALSE:-1)
*************************************************/
BOOL ListEmpty(sqList L)
{   
    return L.length ? FALSE : TRUE;
}

/*************************************************
Function: ClearList 
Description:  將順序表清空 O(1) 
              
              將L->length 置為0即可
Output: *L : 線效能表發生變動
Return: void
*************************************************/
void ClearList(sqList * L)
{
    L->length = 0;
}

/*************************************************
Function: LocateElem
Description: 獲取第一次出現指定元素的位置 O(n)
            
             開始遍歷判斷是否相等 
             返回下下標位置
Input:  
        L : 順序表結構
        e : 指定的元素 
Return: int 具體位置 , 沒找到返回-1 
*************************************************/
int LocateElem(sqList L , ElemType e)
{
    int i = 0;
    for(;i < L.length ; ++i)
    {
        if(L.data[i] == e)
            return i;
    }
    return -1;
}

/*************************************************
Function: ListLength 
Description:  獲取順序表的長度 O(1)
                
              直接返回 L.length即可
Input:  L 表結構
Return: int 順序表的長度
*************************************************/
int ListLength(sqList L)
{
    return L.length;
}

/*************************************************
Function: ListInsert
Description:  
            在順序表的指定位置插入元素 : 時間複雜度O(n) : 時間浪費在移動上面 : 

            插入位置不合理  , return FALSE
            如果 length + 1 > MAXSIZE  return FALSE
            需要將 i 到 length-1的元素向後移動一個位置
            將元素插入指定位置後 , 表的長度 + 1
Input: 
            i : i位置元素的前面進行插入
            e : 被插入的元素
Output:     
            *L: 傳出引數,表示線性表會被修改
Return: 成功 TRUE | 失敗 FALSE
*************************************************/
BOOL ListInsert(sqList * L , int i  , ElemType  e)
{
    int j = 0;
    if( 0>i || i > L->length || L->length + 1 > MAXSIZE)
        return FALSE;

    for(j = i+1 ; j <=L->length ; ++j)
        L->data[j] = L->data[j-1];

    L->data[i] = e;
    L->length+=1;

    return TRUE;
}

/*************************************************
Function: ListDelete
Description: 刪除指定位置的元素 : O(n) 時間也是浪費在移動資料上面 :

             如果刪除的位置不合適: return FALSE
             取出刪除的元素
             將 i 位置之後的元素都向前移動一個元素:
             表的長度需要減去 1 
Input:  
        i : 刪除元素的位置 :  0<=i<=L->length-1
Output:
        L : 表會發生變動
        e : 輸出被刪除的元素
Return: 刪除成功 TRUE | 失敗 FALSE
*************************************************/
BOOL ListDelete(sqList * L , int i , ElemType * e)
{
    int j = 0;
    if(0 == L->length || 0 > i || i >= L->length)
            return FALSE;

    *e = L->data[i];

    for(j = i+1 ; j <=L->length ; ++j)
    {
        L->data[j-1] = L->data[j];
    }

    L->length-=1;
    return TRUE;
}


/*************************************************
Function: GetElem
Description: 獲取順序表中指定位置的元素 , 時間複雜度O(n) , 時間浪費在遍歷上面:
            
             i位置不合理 return FALSE
             取得i位置的元素
        
Input: 
      L  : 順序表結構
      i  : 獲取元素的位置 ,  0<= i <= L.length-1 
Output: 
      *e : 輸出型別引數 , 獲取 i 指向的元素  
Return: 成功TRUE | 失敗 FALSE
*************************************************/
BOOL GetElem(sqList L , int i  , ElemType * e)
{
    /* i 是從0 開始計算的*/
    if(0 == L.length || i < 0 || i > L.length-1)
        return FALSE;
    *e = L.data[i];
    return TRUE;
}
sqList 操作的實現

宗上看出:  

  主要操作:
    插入 , 刪除 O(n)
    搜尋 , 修改 O(1)

線效能表儲存結構的優點和缺點:

  • 優點:
    • 無需為表中元素之間的邏輯關係增加額外空間(比如連表 , 需要增加一個指標域)
    • 可以快速的存取表中 任意元素的位置
  • 缺點:
    • 插入 和 刪除操作需要移動大量元素
    • 當線性表的長度變化較大時 , 難以確定儲存空間的容量
    • 造成儲存空間的碎片 [ 可能開闢的空間大小 > 順序表的大小造成 空間的浪費 ]