資料結構 ------- 簡介
資料結構研究非數值計算的程式設計中計算機的操作物件以及他們之間的關係和操作的學科。
在計算機發展初期,人們使用計算機的主要目的的是處理數值計算問題,所以程式設計者的主精力集中於程式設計的技巧上而無需重視資料結構,但隨著計算機應用領域的擴大和軟硬體的發展,非數值計算問顯得越來越重要,使得資料元素之間的相互關係一般無法用數學方程式加以描述。因此解決這類問題的關鍵不再是數學分析和計算方法,而要設計出合適的資料結構才能有效的解決問題。(初期使用計算機解決一個具體問題是一般需要經過,從具體問題中抽象出一個適當的數學模型,然後設計或選擇一個求解此的數學模型演算法,最後編出程式進行除錯測試,直至解決問題)
著名的瑞士電腦科學家沃思(N.Wirth)教授提出:資料結構+演算法=程式
常見名詞:資料 >資料元素 > 資料項
- 資料(Data):描述客觀事物的數、字元以及能輸入計算機中並被計算機處理的符號集合。(如計算機可處理的數字,子符串,圖形、影象、聲音等)
- 資料元素(data element): 資料的基本單位。(如表中一行,樹中一個節點圖中一個頂點),有時一個數據元素可以由若干個陣列項(也稱為欄位、域、屬性)組成,資料項是具有獨立含義的最小標識單位。如(行中的某一單元格)
- 資料物件(data object): 具有相同性質的資料元素的集合,是資料的一個子集。(如字母資料物件是集合{'a','b','c','d','z'})
一、資料結構(data structure)是帶有結構的資料元素的集合。
(結構指的是資料元素之間的相互關係,即資料的組織形式,結構中的資料元素稱為節點),無論怎樣定義資料結構,都應該將資料的邏輯結構、儲存結構及運算三方面看成一個整體。
- 儲存結構是邏輯關係的映像與元素本身的映像
- 邏輯結構是資料結構的抽象,儲存結構是資料結構的實現
1、邏輯結構的種類: 線性結構與非線性結構
線性結構:有且僅有一個開始和一個終端節點,並且所有結點都最多隻有一個直接前趨和一個直接後繼
如:線性表,棧、佇列、串
非線性結構: 一個結點可能有多個直接前趨和直接後繼
如:樹、圖、網
其他劃分如四種劃分:集合結構(資料元素同屬一個集合),線性結構(一對一),樹形結構(一對多),圖或網狀結構(多對多關係)
2、儲存結構
- 順序儲存結構:一組連續的儲存單元依次儲存資料元素,資料元素之間的邏輯關係由元素的儲存位置決定
- 鏈式儲存結構:一組任意的儲存單元儲存資料元素,資料元素之間的邏輯關係用指標來表示,儲存時記住頭指標並存儲下一個元素的地址
- 索引儲存結構:在儲存結點資訊的同時,還建立附加索引表,就像一本書的目錄,目錄就像索引表,通過目錄中的標題找到具體的資訊,方便多資料的查詢。(**在索引表中,每一項稱為索引項,索引項一般由關鍵詞和地址組成,關鍵詞時唯一標識一個結點的資料項**,其中若每個結點在索引表中都有一個索引項,則該索引表稱為稠密索引。若一組結點在索引表中只對應一個索引項,則該索引表稱為稀疏索引)
- 雜湊儲存結構:根據結點的關鍵字直接計算出該結點的儲存地址,
3、資料的運算,即對元素施加的操作(行為)
資料的運算時定義在資料的邏輯結構上的,每種邏輯結構都有一個運算的集合,最常用的運算有:檢索、插入、刪除、更新、排序等
- 檢索:檢索就是在資料結構裡查詢滿足一定條件的節點。一般是給定一個某欄位的值,找具有該欄位值的節點。
- 插入:往資料結構中增加新的節點。
- 刪除:把指定的結點從資料結構中去掉。
- 更新:改變指定節點的一個或多個欄位的值。
- 排序:把節點按某種指定的順序重新排列。例如遞增或遞減。
二、資料型別和抽象資料型別
1、資料型別: 資料型別= 值的集合 + 值集合上的一組操作
定義:一組性質相同的值的集合以及定義於這個值集合上的一組操作的總稱。
作用:約束變數的取值範圍 和 約束變數或常量的操作
2、抽象資料型別(abstract data type)
定義:指一個數學模型以及定義在此數學模型上的一組操作,
特點:由使用者定義,從問題抽象出邏輯結構(資料模型),並定義在資料模型上的相關操作,不考慮計算機內的具體儲存結構與運算的具體實現演算法。
如定義一個某某類,這個類可以進行一些操作
形式定義(簡潔嚴謹的定義):可用 D(資料**物件**),S(D上的**關係**集),P(D的基本**操作**集) 三元組表示
//抽象資料型別的定義格式 ADT 抽象資料型別名{ 資料物件:<資料物件的定義> 資料關係:<資料關係的定義> 基本操作:<基本操作的定義> }ADT 抽象資料型別名
其中:資料物件,資料關係的定義用虛擬碼描述,
基本操作的定義格式為:基本操作名(引數表)、初始條件(初始條件描述)、操作結果(操作結果描述)
引數表:
賦值引數只為操作提供輸入值
引用引數以&打頭,除可提供輸入值外,還將返回操作結果
初始條件:描述操作執行之前資料結構和引數應滿足的條件,若不滿足,則操作失敗,並返回相應的出錯資訊。為空則省略
操作結果:說明正常操作完成後,資料結構的變化狀況和應返回的結果
三、演算法
演算法的描述:自然語言(英文,中文,,),流程圖(傳統流程圖,NS流程圖),虛擬碼(類語言),程式程式碼(c,java)
執行演算法所耗費的時間為時間複雜性。
執行演算法所耗費的儲存空間,主要是輔助空間,為空間複雜性
演算法應易於理解,易於程式設計,易於除錯等,即可讀性和可操作性
1、演算法的五個特性:
- 有窮性:一個演算法必須總是在執行有窮之後結束,且每一步都在有窮時間內完成
- 確定性:演算法中的每一個指令必須有確切的含義,沒有二義性,在任何條件下,只有唯一的一條執行路徑,即對於相同的輸入只能得到相同的輸出
- 可行性:演算法是可執行的,演算法描述的操作可以通過已經實現的基本操作執行有限次來實現
- 輸入:一個演算法有零個或多個輸入
- 輸出:一個演算法有一個或多個輸出
2、設計演算法:注意四個方面:正確性(對於精心選擇的、典型的、苛刻的且帶有刁難性的輸入可得到滿意的結果)、可讀性(易於人理解)、健壯性(對出現錯誤時,有處理方法)、高效性(執行時間短)
3、演算法效率:時間效率(執行演算法耗費的時間)、控制元件效率(演算法執行過程中耗費的空間)
演算法時間效率的度量:演算法編制的程式在計算機上執行所消耗的時間
兩種方式:事前分析法和事後統計(一般不用)
演算法執行時間 = 一個簡單操作所消耗的時間 * 簡單操作次數
演算法執行時間 =∑ 每條語句頻度 * 該語句執行一次所需的時間
由於每條語句執行一次所需的時間,一般由機器決定,因此可假設每條語句所需的時間均為單位時間,此時演算法的執行時間就可轉變為對演算法中語句執行次數,即頻率之和
演算法中基本語句重複執行的次數時問題規模 n 的某個函式 f(n) ,演算法時間度量記作:T(n) = O(f(n))
T(n) = O(f(n)) 表示隨著n的增大,演算法執行的時間的增長率和f(n) 的增長率相同,稱漸近時間複雜度
演算法中基本語句重複執行的次數中問題規模n 的某個函式f(n) ,演算法時間量度記作T(n) = O(f(n))
(n越大演算法執行時間越長:排序中n為記錄數,矩陣中n為矩陣的階數,多項式中n 為多項式的項數,集合中n為元素個數,樹中n為樹的結點個數,圖中n為圖的頂點數或邊數)
4、分析演算法時間複雜度的基本方法:
- 找出語句頻度最大的那條語句作為基本語句
- 計算基本語句的頻度得到問題規模n 的某個函式 f(n)
- 取其數量級用符號 "O" 表示
注意要求找出基本語句的
定理:極限求值,忽略所有低次冪項和最高次冪係數,體現出增長lu
有的情況演算法中的基本操作重複執行的次數還隨問題的輸入資料集不同而不同,因此要考慮最壞,最好和平均時間複雜度,一般總是考慮最壞時間複雜度
對於複雜演算法,可以將它分成幾個容易估算的部分,然後利用加法法則和乘法法則,計算演算法時間複雜度
常見的時間複雜度按數量級遞增排列,依次為:常數階O(1)、對數階O(log2n)、線性階O(n)、線性對數階O(nlog2n)、平方價O(n2)、立方階O(n3)、k次方階O(nk)、指數階O(2n)、階乘階O(n!)
5、空間複雜度:演算法所需儲存空間的度量,記作 S(n)= O(f(n)) (其中n 為問題的規模或大小)
演算法要佔用的空間,輸入/ 輸出,指令,常數,變數,輔助空間(存放臨時資料)等
如:將一個數組逆序存放的兩種方式,一個是藉助第三臨時變數,另一個藉助另一陣列變數