靜態鍊錶dd

2022-07-26 02:09:16 字數 3248 閱讀 1570

《順序表和煉表優缺點》一節,我們了解了兩種儲存結構各自的特點,那麼,是否存在一種儲存結構,可以融合順序表和煉表各自的優點,從而既能快速訪問元素,又能快速增加或刪除資料元素。

靜態鍊錶,也是線性儲存結構的一種,它兼顧了順序表和煉表的優點於一身,可以看做是順序表和煉表的公升級版。

使用靜態鍊錶儲存資料,資料全部儲存在陣列中(和順序表一樣),但儲存位置是隨機的,資料之間"一對一"的邏輯關係通過乙個整形變數(稱為"游標",和指標功能類似)維持(和鍊錶類似)。

例如,使用靜態鍊錶儲存的過程如下:

建立乙個足夠大的陣列,假設大小為 6,如圖 1 所示:

圖 1 空陣列

接著,在將資料存放到陣列中時,給各個資料元素配備乙個整形變數,此變數用於指明各個元素的直接後繼元素所在陣列中的位置下標,如圖 2 所示:

圖 2 靜態鍊錶儲存資料

通常,靜態鍊錶會將第乙個資料元素放到陣列下標為 1 的位置(a[1])中。

圖 2 中,從 a[1] 儲存的資料元素 1 開始,通過儲存的游標變數 3,就可以在 a[3] 中找到元素 1 的直接後繼元素 2;同樣,通過元素 a[3] 儲存的游標變數 5,可以在 a[5] 中找到元素 2 的直接後繼元素 3,這樣的迴圈過程直到某元素的游標變數為 0 截止(因為 a[0] 預設不儲存資料元素)。

類似圖 2 這樣,通過 "陣列+游標" 的方式儲存具有線性關係資料的儲存結構就是靜態鍊錶。

通過上面的學習我們知道,靜態鍊錶儲存資料元素也需要自定義資料型別,至少需要包含以下 2 部分資訊:

因此,靜態鍊錶中節點的構成用 c 語言實現為:

typedef struct component;

圖 2 顯示的靜態鍊錶還不夠完整,靜態鍊錶中,除了資料本身通過游標組成的鍊錶外,還需要有一條連線各個空閒位置的鍊錶,稱為備用鍊錶。

備用鍊錶的作用是**陣列中未使用或之前使用過(目前未使用)的儲存空間,留待後期使用。也就是說,靜態鍊錶使用陣列申請的物理空間中,存有兩個鍊錶,一條連線資料,另一條連線陣列中未使用的空間。

通常,備用鍊錶的表頭位於陣列下標為 0(a[0]) 的位置,而資料鏈表的表頭位於陣列下標為 1(a[1])的位置。

靜態鍊錶中設定備用鍊錶的好處是,可以清楚地知道陣列中是否有空閒位置,以便資料鏈表新增新資料時使用。比如,若靜態鍊錶中陣列下標為 0 的位置上存有資料,則證明陣列已滿。

例如,使用靜態鍊錶儲存,假設使用長度為 6 的陣列 a,則儲存狀態可能如圖 3 所示:

圖 3 備用鍊錶和資料鏈表

圖 3 中,備用鍊錶上連線的依次是 a[0]、a[2] 和 a[4],而資料鏈表上連線的依次是 a[1]、a[3] 和 a[5]。

假設使用靜態鍊錶(陣列長度為 6)儲存,則需經歷以下幾個階段:

圖 4 未儲存資料之前靜態鍊錶的狀態

當向靜態鍊錶中新增資料時,需提前從備用鍊錶中摘除節點,以供新資料使用。

備用鍊錶摘除節點最簡單的方法是摘除 a[0] 的直接後繼節點;同樣,向備用鍊錶中新增空閒節點也是新增作為 a[0] 新的直接後繼節點。因為 a[0] 是備用鍊錶的第乙個節點,我們知道它的位置,操作它的直接後繼節點相對容易,無需遍歷備用鍊錶,耗費的時間複雜度為o(1)

在圖 4 的基礎上,向靜態鍊錶中新增元素 1 的過程如圖 5 所示:

圖 5 靜態鍊錶中新增元素 1

在圖 5 的基礎上,新增元素 2 的過程如圖 6 所示:

圖 6 靜態鍊錶中繼續新增元素 2

在圖 6 的基礎上,繼續新增元素 3 ,過程如圖 7 所示:

圖 7 靜態鍊錶中繼續新增元素 3

由此,靜態鍊錶就建立完成了。

下面給出了建立靜態鍊錶的 c 語言實現**:

#include

#define maxsize 6

typedef struct component;

//將結構體陣列中所有分量鏈結到備用鍊錶中

void reservearr(component*array);

//初始化靜態鍊錶

int initarr(component*array);

//輸出函式

void displayarr(component * array,int body);

//從備用鍊錶上摘下空閒節點的函式

int mallocarr(component * array);

int main()

//建立備用鍊錶

void reservearr(component*array)

array[maxsize-1].cur=0;//鍊錶最後乙個結點的游標值為0

}//提取分配空間

int mallocarr(component * array)

return i;

}//初始化靜態鍊錶

int initarr(component*array)

array[tempbody].cur=0;//新的鍊錶最後乙個結點的指標設定為0

return body;

}void displayarr(component * array,int body)

printf("%d,%d\n",array[tempbody].data,array[tempbody].cur);

}**輸出結果為:

靜態鍊錶為:

-1,2 1,3 2,4 3,0

提示,此**建立了乙個帶有頭節點的靜態鍊錶,因此最先輸出的 "-1,2" 表示的是頭節點(-1表示此處未儲存資料),其首元節點(儲存元素 1 的節點)在陣列 array[2] 中。

鍊錶學習 靜態鍊錶

struct linknode 鍊錶在指定位置插入與刪除元素不需要移動元素,只需要修改指標即可,而陣列刪除與加入元素則需要移動後面的元素,鍊錶相對於陣列來講,則多了指標域空間開銷,拿到鍊錶第乙個節點就相當於拿到整個鍊錶 鍊錶的分類 靜態鍊錶,動態鍊錶 單向鍊錶,雙向鍊錶,迴圈鍊錶,單向迴圈鍊錶,雙向...

靜態鍊錶(陣列 鍊錶和靜態鍊錶的操作)

因為是線性表,不能只講鍊錶,所以今天提一下靜態鍊錶以及陣列 鍊錶 靜態鍊錶之間的對比。陣列基本結構沒得說,插入和刪除的操作也是有的 雖然看著不比較詭異 一般是動態分配乙個足夠長的,記錄有多少個元素後對這個個數進行加減,而不是每插入乙個就動態分配 其實這樣也行,要是不怕麻煩的話 另外在插入刪除操作之後...

靜態鍊錶和迴圈鍊錶

所謂靜態鍊錶,與指標型描述的鍊錶 動態鍊錶 的區別在於靜態鍊錶借用一維陣列來描述鍊錶.這種儲存型別需要預先分配乙個較大的空間.其結構如下圖 與動態鍊錶操作時最大的區別在於 靜態鍊錶需由使用者自己實現malloc和free函式.為了辨明陣列中哪些分量未被使用,解決的辦法是 將所有未被使用過的以及被刪除...