1. 程式人生 > >數據結構(一)線性表

數據結構(一)線性表

移動 選擇 技術分享 這就是 width win 空指針 新元素 塊存儲

線性表

基本概念

  線性表是一種線性結構,在一個線性表中數據元素的類型是相同的,或者說線性表是由 同一類型的數據元素構成的線性結構。

  定義:線性表是具有相同數據類型的n(n≥0)個數據元素的有限序列,通常記為: (a1,a2,… ai-1,ai,ai+1,…an) 其中n為表長, n=0 時稱為空表。 需要說明的是:ai為序號為 i 的數據元素(i=1,2,…,n),通常將它的數據類型抽象為 ElemType,ElemType根據具體問題而定。

線性表的實現

1、線性表的順序存儲結構

(1)順序表

  線性表的順序存儲是指在內存中用地址連續的一塊存儲空間順序存放線性表的各元素, 用這種存儲形式存儲的線性表稱其為順序表。

  設a1的存儲地址為Loc(a1),每個數據元素占d個存儲地址,則第i個數據元素的地址為: Loc(a i)=Loc(a1)+(i-1)*d 1≤i≤n 這就是說只要知道順序表首地址和每個數據元素所占地址單元的個數就可求出第i個數 據元素的地址來,這也是順序表具有按數據元素的序號隨機存取的特點。

(2)順序表上基本運算的實現

  順序表的初始化:順序表的初始化即構造一個空表,這對表是一個加工型的運算,因此,將L設為引用參數, 首先動態分配存儲空間,然後,將length置為0,表示表中沒有數據元素。

  順序表的插入運算

線性表的插入是指在表的第i(i的取值範圍: 1≤i≤n+1)個位置上插入一個值為 x 的新元素, 插入後使原表長為 n的表成為表長為 n+1 表。

順序表上完成這一運算則通過以下步驟進行: ① 將ai~an 順序向下移動,為新元素讓出位置;(註意數據的移動方向:從後往前依次 後移一個元素) ② 將 x 置入空出的第i個位置; ③ 修改表長。

?   刪除運算

線性表的刪除運算是指將表中第 i (i 的取值範圍為 :1≤ i≤n)個元素從線性表中去掉, 刪除後使原表長為 n 的線性表成為表長為 n-1 的線性表。

順序表上完成這一運算的步驟如下: ① 將ai+1~an 順序向上移動;(註意數據的移動方向:從前往後依次前移一個元素) ② 修改表長。

順序表的刪除運算與插入運算相同,其時間主要消耗在了移動表中元素上。

2、線性表的鏈式存儲結構

  單鏈表

表示 :鏈表是通過一組任意的存儲單元來存儲線性表中的數據元素的。為建立起數據元素之間 的線性關系,對每個數據元素ai,除了存放數據元素的自身的信息 ai 之外,還需要和ai一起 存放其後繼 ai+1 所在的存儲單元的地址,這兩部分信息組成一個“結點”。其中,存放數據元素信息的稱為數據域,存放其後繼地址的稱為指針域。

單鏈表上基本運算的實現

  建立單鏈表:

●頭插法——在鏈表的頭部插入結點建立單鏈表

  鏈表與順序表不同,它是一種動態管理的存儲結構,鏈表中的每個結點占用的存儲空間 不是預先分配,而是運行時系統根據需求而生成的,因此建立單鏈表從空表開始,每讀入一 個數據元素則申請一個結點,然後插在鏈表的頭部。

●尾插法——在單鏈表的尾部插入結點建立單鏈表

  頭插入建立單鏈表簡單,但讀入的數據元素的順序與生成的鏈表中元素的順序是相反的, 若希望次序一致,則用尾插入的方法。因為每次是將新結點插入到鏈表的尾部,所以需加入 一個指針 r 用來始終指向鏈表中的尾結點,以便能夠將新結點插入到鏈表的尾部。

頭結點的加入會帶來以下兩個優點

  第一個優點:由於開始結點的位置被存放在頭結點的指針域中,所以在鏈表的第一個位 置上的操作就和在表的其它位置上的操作一致,無需進行特殊處理;

  第二個優點:無論鏈表是否為空,其頭指針是指向頭結點在的非空指針(空表中頭結點 的指針域為空),因此空表和非空表的處理也就統一了。

查找操作:

●按序號查找 Get_LinkList(L,i)

  從鏈表的第一個元素結點起,判斷當前結點是否是第i個,若是,則返回該結點的指針, 否則繼續後一個,表結束為止,沒有第i個結點時返回空。

插入運算

●後插結點:設p指向單鏈表中某結點,s指向待插入的值為x的新結點,將s插入到p的 後面。

  操作如下: ①s->next=p->next; ②p->next=s; 註意:兩個指針的操作順序不能交換。

刪除運算

●刪除結點 設p指向單鏈表中某結點,刪除p。要實現對結點p的刪除,首先要找到 p的前驅結點q,然後完成指針的操作即可。

  操作如下:①q=L; while (q->next!=p) q=q->next; //找*p的直接前驅

?        ②q->next=p->next; free(p);

循環鏈表

  對於單鏈表而言,後一個結點的指針域是空指針,如果將該鏈表頭指針置入該指針域, 則使得鏈表頭尾結點相連,就構成了單循環鏈表。

雙向鏈表

  每個結點再加一個指向前驅的指針域,用這種結點組成的鏈表稱為雙向鏈表。

雙向鏈表中結點的插入:設 p 指向雙向鏈表中某結點,s 指向待插入的值為 x 的新結點, 將s 插入到p 的前面。

  操作如下: ① s->prior=p->prior; ② p->prior->next=s; ③ s->next=p; ④ p->prior=s;

指針操作的順序不是唯一的,但也不是任意的,操作①必須要放到操作④的前面完成, 否則*p 的前驅結點的指針就丟掉了。

雙向鏈表中結點的刪除:設 p 指向雙向鏈表中某結點,刪除*p。

操作如下: ①p->prior->next=p->next; ②p->next->prior=p->prior; free(p);

順序表和鏈表的比較

順序表 單鏈表
以地址相鄰表示關系 用指針表示關系
隨機訪問,取元素O(1) 順序訪問,取元素O(n)
插入、刪除需要移動元素O(n) 插入、刪除不用移動元素O(n)(用於查找位置)


技術分享圖片

  總之,兩種存儲結構各有長短,選擇那一種由實際問題中的主要因素決定。通常“較穩定” 的線性表選擇順序存儲,而頻繁做插入刪除的即動態性較強的線性表宜選擇鏈式存儲。

數據結構(一)線性表