1.82k likes | 2k Views
計算機概論. 第五章 資料結構. 陳維魁 / 陳邦治 旗標出版社. 本章重點. 二大類主題 表示資料的基本工具 常用的演算法 在設計程式的過程中經常被用來表示資料的基本工具例如陣列、鏈結串列、堆疊、樹狀結構及圖形等都算是資料的結構 在撰寫程式的過程中所經常使用的演算法例如搜尋法、排序法、樹及圖形的追蹤法等都是資料結構所含括的內容 資料結構、演算法及程式設計這三個主題彼此間具有密不可分的關係. 大綱. 陣列 (array) 鏈結串列 (linked list) 堆疊與佇列 (stack and queue) 樹 (tree) 搜尋作業 (searching)
E N D
計算機概論 第五章 資料結構 陳維魁/陳邦治 旗標出版社
本章重點 • 二大類主題 • 表示資料的基本工具 • 常用的演算法 • 在設計程式的過程中經常被用來表示資料的基本工具例如陣列、鏈結串列、堆疊、樹狀結構及圖形等都算是資料的結構 • 在撰寫程式的過程中所經常使用的演算法例如搜尋法、排序法、樹及圖形的追蹤法等都是資料結構所含括的內容 • 資料結構、演算法及程式設計這三個主題彼此間具有密不可分的關係
大綱 • 陣列(array) • 鏈結串列(linked list) • 堆疊與佇列(stack and queue) • 樹(tree) • 搜尋作業(searching) • 排序作業(sorting) • 圖形(graph) 3 3
陣列 • 陣列主要是由陣列的名稱,維度(dimension),元素型態以及陣列註標(index)組成 • 陣列有二項特別的限制 • 必須配置連續的記憶體空間給陣列元素使用 • 陣列中所有元素的型態必須完全相同,也就是說每個元素所佔用的記憶體空間必須是相同的
範例 • 若A是一個包含5個元素的陣列,元素的型態為整數。若整數型態資料佔用記憶體的空間為2個位元組,假設配置給陣列A的記憶體位址由100開始,利用A[1]、A[2]、A[3]、A[4]及A[5]來表示陣列的5個元素,則陣列A的所有元素之記憶體空間使用情形將如下圖所示 由上圖知A[1]、A[2]、A[3]、A[4]及A[5]佔用了連續的記憶體空間且因為元素的型態相同,因此使用的記憶體空間也相同
陣列儲存方法 • 陣列在記憶體中的儲存方式 • 「以列為優先」(row major ordering) • 「以行為優先」(column major ordering) • 「以列為優先」是在編排陣列中元素之順序時,由最右邊的註標值開始進位 • 「以行為優先」則是在編排陣列中元素之順序時,由最左邊的註標值開始進位 • 以列為優先法較符合人類的習慣,因此除了FORTRAN採用「以行為優先」外,其他的程式語言多是採用「以列為優先」
範例 • 請針對二維陣列X[1:3, 1:5],說明「以列為優先」陣列元素在記憶體中排列的順序
範例 • 請針對二維陣列X[1:3, 1:5],說明「以行為優先」陣列元素在記憶體中排列的順序
陣列求址公式 • 對於陣列中特定的元素若要知道儲存該元素的記憶體空間之位址,必須利用陣列求址公式來計算 • 陣列求址公式分為 • 一維陣列 • 二維陣列 • 多維陣列
一維陣列求址公式 • 陣列為X(l:u),其中l為陣列之註標下限,u為陣列之註標上限,w為每個元素所使用的記憶體空間大小 • 陣列元素個數:(u- l+1)。 • 陣列佔用記憶體空間量:(u- l+1)×w。 • 陣列X的位址函數L:L(X[i])=α+w×(i-l) 其中α為陣列X在記憶體中之起始位址
一維陣列求址範例 • 假設一陣列規格如下:int X [1:100];陣列起始為20,一個整數佔用二個記憶體空間,則X這個陣列佔用的記憶體空間的計算方法如下
二維陣列求址公式 • 陣列為X(l1:u1, l2:u2),其中l1為陣列左方維度之註標下限,u1為陣列左方維度之註標上限,l2為陣列右方維度之註標下限,u2為陣列右方維度之註標上限 • 陣列元素個數:(u1- l1+1)×(u2- l2+1) • 陣列佔用記憶體空間量:(u1- l1+1)×(u2- l2+1)×w • 陣列X的位址函數,分為「以列為優先」及「以行為優先」二種,假設α為陣列X在記憶體中之起始位址: • 「以列為優先」位址函數: • Lrow (X[i,j])=α+w×[(i-l1)×(u2- l2+1)+(j-l2)] • 「以行為優先」位址函數: • Lcolumn (X[i,j])=α+w×[(j-l2)×(u1- l1+1)+(i-l1)]
二維陣列求址範例 • 假設一陣列規格如下:int X [1:100, 5:90];陣列起始為20,一個整數佔用二個記憶體空間,則X陣列佔用的記憶體空間的計算方法如下
多維陣列求址範例 • 三維陣列A[1:4;0:5;2:6],共有幾個元素? • 解:120 分別計算各個維度元素的個數: 「1:4」:有4個元素,「0:5」:有6個元素,「2:6」:有5個元素。 將各個維度元素的個數相乘即為所求:4×6×5=120。 由以上說明可知,題意的三維陣列A共有120個元素
特殊矩陣表示法 • 矩陣便是二維陣列 • 介紹三種特殊矩陣表示法 • 稀疏矩陣(sparse matrix) • 下三角矩陣(lower triangular matrix) • 上三角矩陣(upper triangular matrix)
稀疏矩陣 • 稀疏矩陣是指矩陣中非零的元素數量很少,常用的表示法有「直接表示法」及「列-行索引表示法」(row-column indexing)二種
稀疏矩陣--直接表示法 直接利用二維陣列A來表示稀疏矩陣。因稀疏矩陣共有25個元素, A便需宣告為有25個元素的二維陣列,一個陣列元素存在一個矩陣元素,對應關係如下頁
稀疏矩陣--列-行索引表示法 • int A[S] [3]; • S : 總非零項個數 • A [0] [0] : 總列數 • A [0] [1] : 總行數 • A [0] [2] : 非零項總個數 • 第i個非零項相關資料如下(由左而右,由上而下): • A [i] [0] : 所在列數 • A [i] [1] : 所在行數 • A [i] [2] : 值
下三角矩陣 • 「下三角矩陣」是指矩陣內對角線以上(不含對角線)所有元素之值皆為0,如右圖 • 以列為主序(即依照第一列,第二列,…,第n列之順序),將「下三角矩陣」依序儲存則,aij元素代表第i列第j行的元素,相當於「下三角矩陣」中第[1+2+…+(i-1)]+j = 個元素 • 以行為主序(即依照第一行,第二行,…,第n行之順序)把「下三角矩陣」則aij元素代表第i列第j行的元素,相當於「下三角矩陣」中第[n+(n-1)+…+(n-(j-2)]+(i-j)+1 = 個元素
上三角矩陣 • 「上三角矩陣」是指矩陣內對角線以下(不含對角線)所有元素之值皆為0,如右圖所示 • 以列為主序,將「上三角矩陣」依序儲存則,aij元素代表第i列第j行的元素,相當於「上三角矩陣」中第 個元素 • 以行為主序把「上三角矩陣」則aij元素代表第i列第j行的元素,相當於「上三角矩陣」中第[1+2+…+(j-1)]+i = 個元素
鏈結串列 • 鏈結串列(linked list)是寫作程式時,常用的一種資料結構。在鏈結串列中是利用指標來表示元素之下一個元素的位址。常用的格式如下 • 上圖中「資料欄位」用來存放資料內容,若資料項目有多個則可以有多個「資料欄位」,而「鏈結欄位」則是用來存放下一筆資料的位址
鏈結串列實例 • 最後一筆資料的「鏈結欄位」內容為「nil」代表該筆資料的後方已無資料
堆疊 • 堆疊(stack)是指一有序串列(ordered list) • 僅能由一端做加入(add)與刪除(deletion)的動作 • 此端稱作開口端(或頂端),而另一端則稱為封閉端(或底端), • 堆疊 • 先進後出(First In Last Out--FILO) • 後進先出(Last In First Out--LIFO)
堆疊的操作 • 堆疊有下列五項主要操作 • create (新建一個堆疊) • push (加入一新資料項進入堆疊) • pop (由堆疊中刪除一個資料項) • top (讀取出堆疊中最頂端的資料項,但堆疊內容未被破壞) • isempty (檢查是否為空堆疊)
堆疊的操作 – top,從堆疊中讀取最靠近開口端元素之值,但不破壞堆疊之結構
範例 • 若有一堆疊,其內的資料為ABCDEF,其中堆疊頂端的資料是F。假設push(X)代表將資料X壓入堆疊中,而pop代表從堆疊頂端取出資料,試問當堆疊的操作順序是push(X),pop,pop,push(X),pop,pop,push(X),push(X),pop,pop時,完成此序列操作後,堆疊頂端的資料應為何? • ANS: D
運算式的轉換 • 運算式是用來表達計算過程的表示法 • 例如「a+b」便是對運算元(operand) a與b執行加法運算子(operator)之計算 • 運算式常見的表示法有中置式(infix)、前置式(prefix)及後置式(postfix)三種 • 人類習慣採用中置式來表示運算式 • 計算機的運算則是採用前置式或後置式較為方便 • 程式設計師利用中置式來表達計算過程,但這些以中置式寫成的敘述,在計算機處理前會先被轉換成前置式或後置式
中置式 • 將運算子擺放在對應運算元的中間 • <運算元> <運算子> <運算元>;如:x+y。
前置式(prefix) • 將運算子擺放在對應運算元的前面,又稱polish notation • <運算子> <運算元> <運算元>;如:+xy
後置式(postfix) • 將運算子擺放在對應運算元的後面,又稱reverse polish notation • <運算元> <運算元> <運算子>;如:xy+
中置式轉換為前置式 • 將運算式中的運算子以左小括號「(」及右小括號「)」分隔開來,分隔之方式是對每一個運算子加入一組相對應的「(」,「)」且分隔時需考慮運算子運算的優先順序 • 依照運算子的優先順序對「(」,「)」加入編號 • 將運算子取代相對應的「(」,並去除剩餘的所有「)」
中置式轉為後置式 • 將運算式中的運算子以左小括號「(」及右小括號「)」分隔開來,分隔之方式是對每一個運算子加入一組相對應的「(」,「)」且分隔時需考慮運算子運算的優先順序 • 依照運算子的優先順序對「(」,「)」加入編號 • 將運算子取代相對應的「)」,並去除剩餘的所有「(」
範例 • 若有一中置式為A+B-C*D/E請將其轉換為對應的前置式及後置式
範例 • 請利用堆疊對以下前置式作求值動作: - + A B / * C D E • 利用堆疊對「前置式」作求值動作時,必須由右至左來處理,遇到運算元時將運算元push到堆疊中,遇到運算子時由堆疊中pop出二個運算元執行該運算子之運算後,再將結果push回堆疊中
範例 • 請利用堆疊對以下後置式作求值動作: AB+CD*E/- • 利用堆疊對「前置式」作求值動作時,必須由左至右來處理,遇到運算元時將運算元push到堆疊中,遇到運算子時由堆疊中pop出二個運算元執行該運算子之運算後,再將結果push回堆疊中
範例 • 考慮下面這一個遞迴公式,其中n是正整數f(n)=f(n-1)×n,f(1)=1請問f(100)是什麼? • 解:100! • 本題為求階層值的重要範例,建議由最小的輸入值1開始往目標值100的方向來處理,處理步驟如右
佇列 • 佇列(queue)是一個有序串列,元素的加入與刪除是在不同端進行,所以佇列有先進先出(FIFO)的特性,元素的刪除由前端(front)進行,而元素的插入則由後端(rear)進行
範例 • 若有一佇列,初始時為空佇列。假設Add(X)代表將資料X加入佇列後端,而Delete代表從佇列前端取出資料,試問當佇列的操作順序是Add(A),Add(B),Delete,Add (C),Add (D),Delete,Add (E),Add (F),Delete時,完成此序列操作後,佇列內的資料應為何? • 解:C
佇列的操作 • 佇列有下列五項主要操作,分別是: • create (新建一個佇列) • add (加入一新資料項進入佇列) • delete (由佇列中刪除一個資料項) • front (讀取出佇列中最頂端的資料項,但佇列內容未被破壞) • isempty (檢查是否為空佇列)