1. 程式人生 > >大話資料結構 —— 3.5 順序儲存結構的插入與刪除

大話資料結構 —— 3.5 順序儲存結構的插入與刪除

3.5.1 獲得元素操作

實現GetElem的具體操作,即將線性表L中的第i個位置元素值返回。就程式而言非常簡單了,我們只需要把陣列第i-1下標的值返回即可。

我們來學習下具體的程式碼:getElem.c

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

typedef int Status;

// Status是函式的型別,其值是函式結果狀態程式碼,如OK等。
// 初始條件: 順序線性表L已存在, 1 <= i <= ListLength(L)
// 操作結果: 用e返回L中第i個數據元素的值。

Status GetElem(SqList L,int i,ElemType *e)
{
    if( L.length==0 || i<1 || i>L.length )
    {
        return ERROR;
    }
    *e = L.data[i-1];

    return OK;
}

注意這裡返回值型別Status是一個整型,約定返回1代表OK,返回0代表ERROR。今後還會出現,也是使用同樣的約定,不再詳述。

3.5.2 插入操作

剛才我們也談到,線性表的順序儲存結構具有隨機儲存結構的特點,時間複雜度為O(1)。

大家現在來考慮下,如果我們要實現 ListInsert(*L, i, e)

即線上性表L中的第i個位置插入新元素e,程式碼應該如何寫?

所以插入演算法的思路:

  1. 如果插入位置不合理,丟擲異常;
  2. 如果線性表長度大於等於陣列長度,則丟擲異常或動態增加陣列容量;
  3. 從最後一個元素開始向前遍歷到第i個位置,分別將它們都向後移動一個位置;
  4. 將要插入元素填入位置i處;
  5. 線性表長+1。  

接下來看程式碼ListInsert.c

// 初始條件: 順序線性表L已存在, 1 <= i <= ListLength(L)
// 操作結果: 在L種第i個位置之前插入新的資料元素e,L長度+1

Status ListInsert(SqList *L, int i, ElemType *e)
{
    int k;

    if( L->length == MAXSIZE ) // 順序線性表已經滿了
    {
        return ERROR;
    }

    if( i<1 || i>L->length+1 ) // 當i不在範圍內時
    {
        return ERROR;
    }

    if( i<= L->length ) // 若插入資料位置不在表尾
    {
        // 將刪除位置後繼元素後移        
        for( k=L->length-1; k>=i-1; k--)
        {
            L->data[k+1] = L->data[k];
        }
    }

    L->data[i-1] = e; // 將新元素插入
    L->length++;

    return OK;
}

3.5.3 刪除操作

所以刪除演算法的思路:

  1. 如果刪除位置不合理,丟擲異常;
  2. 取出刪除元素;
  3. 從刪除元素位置開始遍歷到最後一個元素位置,分別將它們都向前移動一個位置;
  4. 表長-1。

實現程式碼: ListDelete.c

// 初始條件: 順序線性表L已存在, 1 <= i <= ListLength(L)
// 操作結果: 刪除L的第i個數據元素,並用e返回其值,L的長度-1

Status ListDelete(SqList *L, int i, ElemType *e)
{
    int k;

    if( L->length == 0 ) // 順序線性表為空
    {
        return ERROR;
    }

    if( i<1 || i>L->length ) // 刪除位置不正確
    {
        return ERROR;
    }

    *e = L->data[i-1];

    if( i< L->length ) // 若插入資料位置不在表尾
    {
        // 將刪除位置後繼元素前移
        for( k=i; k<L->length; k++ )
        {
            L->data[k-1] = L->data[k];
        }
    }

    L->length--;

    return OK;
}

現在我們分析一下,插入和刪除的時間複雜度。

最好的情況:插入和刪除操作剛好要求在最後一個位置操作,因為不需要移動任何元素,所以此時的時間複雜度為O(1)。

最壞的情況:如果要插入和刪除的位置是第一個元素,那就意味著要移動所有的元素向後或者向前,所以這個時間複雜度為0(n)。  

至於平均情況,就取中間值O((n-1)/2)。

按照前邊推導大O指導,平均情況複雜度簡化後還是O(n)。

3.5.4 線性表順序儲存結構的優缺點

線性表的順序儲存結構,在存、讀資料時,

不管是哪個位置,時間複雜度都是0(1)。

而在插入或刪除時,時間複雜度都是0(n)。 這就說明,它比較適合元素個數比較穩定,不經常插入和刪除元素,而更多的操作是存取資料的應用。  

那我們接下來給大家簡單總結下線性表的順序儲存結構的優缺點:

優點:

  1. 無須為表示表中元素之間的邏輯關係而增加額外的儲存空間。
  2. 可以快速地存取表中任意位置的元素。

缺點:

  1. 插入和刪除操作需要移動大量元素。
  2. 當線性表長度變化較大時,難以確定儲存空間的容量。
  3. 容易造成儲存空間的“碎片”