《大話數據結構》讀書筆記
閱讀時,摘抄是非常好的習慣。“最淡的墨水也勝于最強的記憶!"有不少讀者會認為摘抄了將來也不會再去看,有什么必要,但其實在寫字的過程就是大腦學習的過程,寫字在減緩你閱讀的速度,從而讓你更好地消化閱讀的內容。相信大家都能理解,“囫圇吞棗"和“慢慢品味”的差異,學習同樣如此。
★★★★☆7.9
程杰 / 2011 / 清華大學出版社
程序 = 數據結構 + 算法
第一章 數據結構緒論
1.4.1 數據
數據:是描述客觀事物的符號,是計算機中可操作的對象,是能被計算機識別,并輸入給計算機處理的符號集合。
1.4.2 數據元素
數據元素:是組成數據的,有一定意義的基本單位,在計算機中通常作為整理處理,也被成為記錄。
1.4.3 數據項
數據項:一個數據可以由若干個數據項組成;
數據項是數據不可分割的最小單位
1.4.4 數據對象
數據對象:是性質相同的數據元素的集合,是數據的子集。
1.4.5 數據結構
數據結構:是相互之間存在一種或多種特定關系的數據元素集合
在計算機中,數據元素并不是孤立、雜亂無序的,而是具有內在聯系的數據集合。數據元素之間存在的一種或多種特定關系,也就是數據的組織形式。
1.5 邏輯結構與物理結構
1.5.1 邏輯結構
- 集合結構
集合結構:集合結構中的數據元素除了同屬于一個集合外,沒有其他關系。
[](javascript:;)[](javascript:;)[](javascript:;)
[刪除](javascript:;)[集合結構](javascript:;)
- 線性結構
線性結構:線性結構中的數據元素是一對一的關系
[](javascript:;)[](javascript:;)[](javascript:;)
[刪除](javascript:;)[線性結構](javascript:;)
- 樹形結構
樹形結構:樹形結構中的數據元素之間存在一種一對多的層次關系
[](javascript:;)[](javascript:;)[](javascript:;)
[刪除](javascript:;)[樹形結構](javascript:;)
- 圖形結構
圖形結構: 圖形結構的數據元素是多對多的關系
[](javascript:;)[](javascript:;)[](javascript:;)
[刪除](javascript:;)[圖形結構](javascript:;)
1.5.2 物理結構
物理結構:是指數據的邏輯結構在計算機中的存儲形式。
- 順序存儲結構
開辟一段連續的空間,依次按順序存放數據元素。
[](javascript:;)[](javascript:;)[](javascript:;)
[刪除](javascript:;)[順序存儲結構](javascript:;)
- 鏈式存儲結構
現在如銀行、醫院等地方,設置了排隊系統,也就是每個人去了,先領一個號,等著叫號,叫到時去辦理業務或看病。在等待的時候,你愛在哪在哪,可以坐著、站著或者走動,甚至出去逛一圈,只要及時回來就行。你關注的是前一個號有沒有被叫到,叫到了,下一個就輪到了。
[](javascript:;)[](javascript:;)[](javascript:;)
[刪除](javascript:;)[鏈式存儲結構](javascript:;)
1.6 抽象數據類型
1.6.1
事實上,抽象數據類型體現了程序設計中問題分解、抽象和信息隱藏的特性。抽象數據類型把實際生活中的問題分解為多個規模小且容易處理的問題,然后建立一個計算機能處理的數據模型,并把每個功能模塊的實現細節作為一個獨立的單元,從而使具體實現過程隱藏起來。
第一章總結
[](javascript:;)[](javascript:;)[](javascript:;)
[刪除](javascript:;)[數據](javascript:;)
第二章 算法
算法:算法是解決特定問題求解步驟的描述,在計算機中表現為指令的有限序列,并且每條指令表示一個或多個操作。
為了解決某個或某類問題,需要把指令表示成一定的操作序列,操作序列包括一組操作,每一個操作都完成特定的功能,這就是算法了。
算法具有五個基本特性:輸人、輸出、有窮性、確定性和可行性。
算法時間復雜度定義
在進行算法分析時,語句總的執行次數T(n)是關于問題規模n的函數,進而分析T(n)隨n的變化情況并確定T(n)的數量級。算法的時間復雜度,也就是算法的時間量度,記作:T(n)=O(f(n))0它表示隨問題規模n的增大,算法執行時間的增長率和f(n)的增長率相同,稱作算法的漸近時間復雜度,簡稱為時間復雜度。其中f(n)是問題規模n的某個函數。
常見的時間復雜度
[](javascript:;)[](javascript:;)[](javascript:;)
[刪除](javascript:;)[(選填) 圖片描述](javascript:;)
記住logN > 1; 2^n < n! < n^n 就好理解了;
第二章總結
算法的定義:算法是解決特定問題求解步驟的描述,在計算機中為指令的有限序列,并且每條指令表示一個或多個操作。
算法的特性:有窮性、確定性、可行性、輸人、輸出。
算法的設計的要求:正確性、可讀性、健壯性、高效率和低存儲量需求。
算法特性與算法設計容易混,需要對比記憶。
算法的度量方法:事后統計方法(不科學、不準確)、事前分析估算方法。在講解如何用事前分析估算方法之前,我們先給出了函數漸近增長的定義。函數的漸近增長:給定兩個函數f(n)和g(n),如果存在一個整數N,使得對于所有的n>N,f〔n〕總是比g〔n)大,那么,我們說f〔n)的增長漸近快于g〔n)。于是我們可以得出一個結論,判斷一個算法好不好,我們只通過少量的數據是不能做出準確判斷的,如果我們可以對比算法的關鍵執行次數函數的漸近增長性,基本就可以分析出:
某個算法,隨著n的變大,它會越來越優于另一算法,或者越來越差于另一算法。
第三章 線性表
線性表: 零個或多個數據元素的有限序列
[](javascript:;)[](javascript:;)[](javascript:;)
[刪除](javascript:;)[(選填) 圖片描述](javascript:;)
Data
線性表的數據對象集合為{ai,a2,...,a。},每個元素的類型均為DataTypeo其中,除第一個元素外,每一個元素有且只有一個直接前驅元素,除了最后一個元素an外,每一個元素有且只有一個直接后繼元素。數據元素之間的關系是一對一的關系。
Operation
InitList((L):初始化操作,建立一個空的線性表L
ListEmpty(L):若線性表為空,返回true,否則返回false.
ClearList(*L)· 將線性表清空。
GetEIem(L,i,*e)· 將線性表中的第i個位置元素值返回給e。
LocateElem(L, e):在線性表L中查找與給定值e相等的元素,如果查找成功,該元素在表中序號表 示成功;否則,返回0表示失敗。
ListInsert(*L, i,e):在線性表L中的第個位置插入新元素
ListDeIete(*L,i,*e):刪除線性表中第土個位置元素,并用e返回其值返回
ListLength(L):返回線性表L的元素個數。
數組的長度是存放線性表的存儲空間的長度,存儲分配后這個量是一般是不變的。
線性表的長度是線性表中數據元素的個數,隨著線性表插人和刪除操作的進行,這個量是變化的。
在任意時刻,線性表的長度應該小于等于數組的長度。
所以對于第i個數據元素ai的存儲位置可以有a1推算得出:
LOC(ai) = LOC(a1) + (i - 1) *c
[](javascript:;)[](javascript:;)[](javascript:;)
[刪除](javascript:;)[(選填) 圖片描述](javascript:;)
單鏈表
[](javascript:;)[](javascript:;)[](javascript:;)
[刪除](javascript:;)[(選填) 圖片描述](javascript:;)
單鏈表結構和順序存儲結構
存儲分配方式
● 順序存儲結構用一段連續的存儲單元一次存儲依次存儲線性表的數據元素
● 單鏈表采用鏈式存儲結構,用一組任意的存儲單元存性表的元素
時間性能
● 查找
● 順序存儲結構 O(1)
● 單鏈表O(n)
● 插入和刪除
● 順序存儲結構需要平均移動表長一般的元素,時間為O(n)
● 單鏈表在線出某位置的指針后,插入和刪除時間僅為O(1)
● 空間性能
● 順序存儲結構需要預分配存儲空間,不好控制。
● 單鏈表不需要預分配存儲空間,只要有空間就可以分配,元素個數不受限制
若線性表需要頻繁查找,很少進行插人和刪除操作時,宜采用順序存儲結構。若需要頻繁插人和刪除時,宜采用單鏈表結構.當線性表中的元素個數變化較大或者根本不知道有多大時,最好用單鏈表結構,這樣可以不需要考慮存儲空間的大小問題。而如果事先知道線性表的大致長度,比如一年12個月,一周就是垡期一至星期日共七天,這種用順序存儲結構效率會高很多。
靜態鏈表
首先我們讓數組的元素都是由兩個數據域組成,山和也就是說,數組的每個下標都對應一個山忪和一個curo數據域山,用來存放數據元素,也就是通常我們要處理的數據;而游標cur相當于單鏈表中的next指針,存放該元素的后繼在數組中的下標。我們把這種用數組描述的鏈表叫做靜態鏈表,這種描述方法還有起名叫做游標實現法。
循環鏈表
將單鏈表中終端結點的指針端由空指針改為指向頭結點,就使整個單鏈表形成一個環,這種頭尾相接的單鏈表稱為單循環鏈表,簡稱循環鏈表(circular linked list)。
[](javascript:;)[](javascript:;)[](javascript:;)
[刪除](javascript:;)[(選填) 圖片描述](javascript:;)
雙向鏈表
[](javascript:;)[](javascript:;)[](javascript:;)
[刪除](javascript:;)[(選填) 圖片描述](javascript:;)
第三章 總結
這章主要講線性表,線性表是另個或多個具有相同類型數據元素的有限序列。
然后是線性表的一些基本操作。后面是線性表的兩大結構:順序存儲結構和鏈式存儲結構
[](javascript:;)[](javascript:;)[](javascript:;)
[刪除](javascript:;)[(選填) 圖片描述](javascript:;)
第四章 棧與隊列
4.2 棧的定義
棧(stack)是限定僅在表尾進行插入和刪除的線性表
[](javascript:;)[](javascript:;)[](javascript:;)
[刪除](javascript:;)[(選填) 圖片描述](javascript:;)
兩個棧共享空間
[](javascript:;)[](javascript:;)[](javascript:;)
[刪除](javascript:;)[(選填) 圖片描述](javascript:;)
想想極端的情況,若棧2是空棧,棧1的topl等于n一1時,就是棧1滿了。反之,當棧1為空棧時,top2等于0時,為棧2滿。但更多的情況,兩個棧見面之時,也就是兩個指針之間相差1時,即topl+1==top2為棧滿。
4.6 棧的鏈式存儲結構及實現
[](javascript:;)[](javascript:;)[](javascript:;)
[刪除](javascript:;)[(選填) 圖片描述](javascript:;)
棧的引人簡化了程序設計的問題,劃分了不同關注層次,使得思考范圍縮小,更加聚焦于我們要解決的問題核心。反之,像數組等,因為要分散精力去考慮數組的下標增減等細節問題,反而掩蓋了問題的本質。
4.8 棧的遞歸
[](javascript:;)[](javascript:;)[](javascript:;)
[刪除](javascript:;)[(選填) 圖片描述](javascript:;)
遞歸函數: 在高級語言中,調用自己和其他函數并沒有本質的不同。我們把一個直接調用自己或通過一系列的調用語句間接地調用自己的函數,稱做遞歸函數。
當然,寫遞歸程序最怕的就是陷人永不結束的無窮遞歸中,所以,每個遞歸定義必須至少有一個條件滿足時遞歸不再進行,即不在引用自身,而是以返回值退出。
4.10 隊列
隊列(queue)是只允許在一段進行插入,在另一端進行刪除的線性表。
先進先出(First In First Out)與醒了
[](javascript:;)[](javascript:;)[](javascript:;)
[刪除](javascript:;)[(選填) 圖片描述](javascript:;)
4.12.2 循環隊列定義
所以解決假溢出的辦法就是后面滿了,就再從頭開始,也就是頭尾相接的循環。我們把隊列的這種頭尾相接的順序存儲結構稱為循環隊列。