线性表简介
目錄
- 線性表的定義
- 抽象數據類型
- 線性表的存儲結構
- 一、線性表的順序存儲結構
- 順序表
- 靜態順序表
- 動態順序表
- 二、線性表的鏈式存儲結構
- 單鏈表
- 不帶頭結點的單鏈表
- 帶頭結點的單鏈表
線性表的定義
線性表(List): 由零個或者多個數據元素組成的有限序列。
線性表首先它是一個序列,也就是說元素之間是有先來后到的。
若元素存在多個,則第一個元素無前驅,而最后一個元素無后繼,其他元素都只有一個直接前驅,和只有一個直接后繼。
線性表的定義:
若將線性表記為(a1,a2,…an-1,an),則表中an-1領先于an,an領先于an+1,稱an-1是an的直接前驅元素,an+1是an的直接后繼元素。
所以線性表元素的個數n(n>=0)定義為線性表的長度,當n=0時,稱為空表。
抽象數據類型
抽象數據類型:就是把數據類型和相關的操作捆綁一起。
抽象數據類型的標準化格式:
ADT 抽象數據類型名
Data
數據元素之間邏輯關系的定義
Operation
操作
endADT
線性表的抽象數據類型
ADT 線性表(List)
Data
線性表的數據對象集合為{ a1,a2,a3,a4…an},每個元素的類型均為ElemType(這里假設元素的類型為ElemType)。
其中,除了 第一個元素a1外,每一個元素都有且只有一個直接前驅元素,除了最后一個元素an外,每一個元素都有且
只有一個直接后繼元素。數據元素之間的關系是一 一對應的。
Operation
InitList(&L): 初始化得到一個空表L,初始化成功返回0 ,否則返回-1。
ListEmpty(L): 判斷表是否空。如果空返回 1 否則返回 0。
ListFull(L): 判斷表是否滿,如果滿的話返回 1 否則返回 0。
CreateList(&L): 如果創建成功返回 1 否則返回 錯誤代碼。
ListLength(L): 返回表的長度。
LocateElem(L,e) : 查找e在表中的位置,找到返回 位序 否則 返回 -1。
ListInsert(&L,i,e): 在表的第 i 個位置插入數據元素 e 插入成功返回 0 否則返回 錯誤信息。
ListDelete(&L,i,&e): 刪除表中的第 i 個數據元素返回被刪除元素的值。刪除成功返回 0 否則返回錯誤代碼。
VisitList(L,i,&e): 訪問線性表第 i 個位置的元素 并用 e 返回元素的值,成功返回 0 失敗返回 錯誤代碼。
ShowList(L): 打印輸出線性表的內容到屏幕或文件中。
DestroyList(&L): 撤銷線性表L ,回收L的存儲空間。
endADT
線性表的存儲結構
線性表的存儲結構分為順序存儲結構和鏈式存儲結構
一、線性表的順序存儲結構
線性表的順序順序存儲是指:用一組地址連續連續的存儲單元來依次存放線性表中的數據。
線性表的順序存儲結構示意圖
順序表
采用順序存儲的線性表簡稱為順序表
這種方式與高級程序設計語言中一維數組的表示和實現相一致,所以也稱為數組表示法。
線性表順序存儲結構的優缺點:
優點:
無須為表示表中元素之間的邏輯關系而增加額外的存儲空間。
可以快速地存取表中任意位置的元素。
缺點:
插入和刪除操作需要移動大量元素。
當線性表長度變化較大時,難以確定存儲空間的容量。
容易造成存儲空間的“碎片”(因為通過數組來存儲的,是一塊連續的存儲空間)
靜態順序表
類型定義
數組的長度與線性表的當前長度需要區分:
數組的長度是存放線性表的存儲空間的總長度,一般初始化后不變。而線性表的當前長度是線性表中元素的個數,是會變化的。
一些簡單的算法
順序表的創建
順序表的插入和刪除
原理圖:
插入算法的思路:
如果插入的位置不合理,拋出異常。
如果線性表長度大于等于數組長度,則拋出異常或動態增加數組容量。
從最后一個元素開始向前遍歷到第 i 個位置,分別將它們都向后移動一個位置。
這時候要插入的位置有空間了,把要插入的數據插入。
表長長度加1。
刪除算法的思路:
如果刪除的位置不合理,拋出異常。
取出刪除的元素。
從刪除元素開始向后遍歷到最后一個元素位置,分別將它們都向前移動一個位置。
表長長度減1。
代碼實現:
我們來分析一下,插入和刪除的時間復雜度。
最好的情況:
插入和刪除操作剛好要求在最后一個位置操作,因為不需要移動任何元素,
所以此時的時間復雜度為O(1)。
最壞的情況:
如果要插入和刪除的位置是第一個元素
那就意味著要移動所有的元素向后或者向前,所以這個時間復雜度為O(n)。
至于平均情況,就取中間值O((n+1)/2)。
按照時間復雜度的化簡規定,平均情況復雜度簡化后為O(n)。
動態順序表
類型定義
一些算法
其他的一些算法和靜態順序表的算法幾乎一樣就不列舉了。
二、線性表的鏈式存儲結構
線性表的鏈式存儲結構:是用一組任意的存儲單元來存儲線性表的數據元素,這組存儲單元可以在內存中的任意位置。也就是說這組存儲單元,可以是連續的,也可以是不連續的,可以是部分連續的也可以是部分不連續的。
在鏈式存儲結構中除了要存儲數據信息外,還要存儲它的后繼元素的存儲地址(指針)。
我們把存儲數據元素信息的域稱為數據域,把存儲直接后繼位置的域稱為指針域。指針域中的信息稱為指針或鏈。這兩部分信息組成的數據元素稱為
結點(Node)。
采用鏈式儲存結構的線性表稱為鏈表。
鏈表中每個結點的存儲地址存放在其前驅結點的next域中,然而首元結點(即第一個結點)無直接前驅,因此,我們需要設置一個頭指針(head)用來存放首元結點的存儲地址。由于,尾元結點(即最后一個結點)無直接后繼,故尾元結點的指針域為空(NULL)。
有時為了在對鏈表進行操作時能夠統一處理空表和非空表的情況,或者能夠統一對首元結點和其他結點的處理過程,我們在鏈表的首元結點之前增設了一個結點,我們稱為頭結點(Head Node)。相對于頭結點而言,其余結點稱為表結點。
頭指針與頭結點的異同:
頭指針
-頭指針是指鏈表指向第一個結點的指針,若鏈表有頭結點,則是指向頭結點的指什。
-頭指針具有標識作用,所以常用頭指針冠以鏈表的名字(指針變量的名字)。
-無論鏈表是否為空,頭指針均不為空。
-頭指針是鏈表的必要元素。
頭結點
-頭結點是為了操作的統一和方便而設立的,放在第一個元素的結點之前, 其數據域一般無意義(但也可以用來存放鏈表的長度)。
-有了頭結點,對在第一元素結點前插入結點和刪除第一結點起操作與其它結點的操作就統一了。
-頭結點不一定是鏈表的必須要素。
單鏈表
單鏈表的結點結構:
不帶頭結點的單鏈表
線性表L(a1 , a2 , a3 , a4…an-1,an)的單鏈表存儲結構為:
帶頭結點的單鏈表
線性表L(a1 , a2 , a3 , a4…an-1,an)的帶頭結點的單鏈表存儲結構為:
總結
- 上一篇: 算法的复杂度
- 下一篇: 概率论-第一章 概率论的基本概念