數據結構知識框架
先概覽一下思惟導圖linux
初識數據結構
概念
-
數據算法
- 描述客觀事物的符號,是計算機中能夠操做的對象,能被計算機識別,並輸入給計算機處理的符號集合
-
數據元素數組
- 是組成數據的、有必定意義的基本單位,在計算機一般做爲總體處理,也被稱爲記錄
-
數據項緩存
- 一個數據元素能夠由若干個數據項組成。數據項是數據不可分隔的最小單位
數據結構形式
-
數據結構網絡
-
具體概念編碼
-
邏輯結構
-
集合結構
- 集合中的數據元素除了同屬一個集合外,它們之間沒有其餘關係
-
線性結構
-
樹形結構
-
圖形結構
-
物理結構
-
順序存儲結構
- 數據元素存放在地址連續的存儲單元裏,其數據間的邏輯關係和物理關係是一致的
-
鏈式存儲結構
- 數據元素存放在任意的存儲單元裏,存儲單元能夠是連續的,也能夠是不連續的
邏輯結構是面向問題的,物理結構是面向計算機的,其基本的目標就是將數據及其邏輯關係存儲到計算機的內存中
程序
算法
算法的複雜度
時間複雜度
空間複雜度
算法分析的分類
時間複雜度--O漸進表示法
-
通常算法O(n)計算法
- 用常數1取代運行時間中的全部加法常數
- 在修改後的運行次數函數中,只保留最高階項
- 若是最高階項係數存在且不是1,則去除與這個項相乘的常數
-
分治算法的時間複雜度計算
- 二分搜索算法的時間複雜度是lgN
- M分搜索算法的時間複雜度爲logM^N
-
遞歸算法的時間複雜度計算
-
遞歸算法空間複雜度算法
遞歸
遞歸定義
- 若一個對象部分的包含它本身或者用它本身給本身定義,則稱這個對象是遞歸的
遞歸的過程
遞歸的思想
- 把問題分解成規模更小的具備與原來問題具備相同解法的小問題
遞歸條件
- 縮小問題規模,使新問題與原問題具備相同的解決方式
- 設置遞歸的出口
遞歸分類
-
數據結構遞歸
-
問題解法遞歸
-
遞歸調用棧
-
尾遞歸
-
遞歸調用返回的結果總被直接返回
-
尾遞歸的本質
- 將單次計算的結果緩存起來,傳遞給下一次調用,至關於自動累積
-
時間複雜度
-
回溯法
遞歸的優缺點
-
優勢
- 遞歸在解決某些問題的時候使得咱們思考的方式的以簡化,代碼也更加簡練,容易閱讀
-
缺點
- 遞歸的實質就是本身調用本身,而函數的調用開銷是很大的,系統要爲每次函數調用分配空間存儲空間,並將調用點信息壓棧,而在函數的調用結束後,還要釋放空間,彈棧恢復斷點,若是遞歸方案的複雜度
棧
棧的概念
特色:後進先出
順序棧
- 順序堆棧和書序表數據成員相同 ,不一樣之處,順序堆棧的入棧和出棧操做只容許對當前棧頂進行
共享棧
-
一個數組實現兩個棧
-
原理
- 既然是兩個棧共享一段空間,向中間靠攏,數組兩端表示兩個棧的棧底,棧頂一直向中間靠近
-
應用場景
- 兩個棧空間需求有相反的關係,也就是一個增加一個縮短的場景
鏈式棧
棧的應用
隊列
只容許在一端插入數據,在另外一端刪除數據的特殊線性表
順序隊列
-
實現方式一
-
實現方式二
-
假溢出現象
- 屢次入隊列、出隊列操做後出現的尚有存儲空間但不能進行入隊列操做的溢出
-
真溢出現象
循環隊列
-
頭尾相接的順序存儲隊列就是循環隊列
-
隊列滿隊列空的判斷
-
少用一個存儲空間
- 隊尾指針加一等於隊頭指針就是隊列滿的判斷條件
- 判空條件是尾和頭相等
-
設計一個標記flag
- 初始flag置爲0,入隊列成功flag=1,出隊列成功flag置爲0
- 隊空條件rearfront&&flag0,
- 堆滿條件rear==front&&flag=1
-
設置一個計數器
- 初始時count=0,入隊列成功,count+1,出隊列成功count-1
- 隊列空的條件count==0
- 隊列滿的條件count>0&&rear==front或者count == MaxSize
鏈式隊列
- 隊列的鏈式存儲結構,其實就是線性表的單鏈表,只不過它只能尾進,頭出而已
優先級隊列
隊列的應用
- 生產者消費者模型
- 消息隊列
- 排隊現象
- 網絡數據傳輸
矩陣
特殊矩陣
- 有不少值相同的元素或有許多零元素,且值相同的元素或零元素的分佈有必定規律的矩陣
對稱矩陣
-
一個N*N矩陣,任意Aij = Aji
-
對稱矩陣壓縮存儲
- 因爲對稱矩陣上三角和下三角是相同的因此只需存一半便可
-
對稱矩陣和對稱壓縮存儲的關係
-
下三角
- i>jSymmetricMatrix[i][j] == Array[i*(i+1)/2+j]
稀疏矩陣
矩陣逆置
初識樹
樹的基本概念
-
由N個節點(N>=0)構成的集合
- 有一個特殊的節點,稱爲根節點,根節點沒有前驅節點
- 除過根節點外,其他節點別分紅M個(M>0)個互不相交的集合T一、T2...Tn,其中每個集合又是一棵與樹結構相似的子樹
- 樹是遞歸定義的
名詞解釋
-
結點
- 結點包括一個數據元素及若干指向其餘子樹的分支(指針(索引))
-
結點的度
-
度爲0的結點
-
分支結點
-
祖先結點
-
子孫結點
-
雙親結點
- 樹中某結點有孩子節點,該結點稱爲它孩子節點的雙親結點
-
孩子結點
-
兄弟結點
-
樹的度
-
結點的層次
-
樹的深度
-
有序樹
-
無序樹
- 樹中結點的各棵子樹之間的次序不重要,能夠相互交換位置
-
森林
樹的表示方法
樹的存儲結構
-
雙親表示法
-
孩子表示法
-
雙親孩子表示法
- 用指針既表示出每一個結點的雙親結點,也表示出每一個結點的孩子結點
-
孩子兄弟表示法
- 表示出第一個結點的第一個孩子結點,也表示出每一個結點的下一個兄弟結點
樹的應用
樹之二叉樹
概念
- 一棵二叉樹是結點的一個有限集合,該集合或者爲空,或者是由一個根節點加上兩棵分別稱爲左子樹和右子樹的二叉樹組成
特色
- 每一個結點最多有兩棵子樹
- 二叉樹的子樹有左右之分,其次序不能顛倒
滿二叉樹
- 全部分支結點都存在左子樹和右子樹,而且全部葉子結點都在同一層上
徹底二叉樹
- 若是一棵具備N個結點的二叉樹的結構與滿二叉樹的前N個節點 的結構相同,稱爲徹底二叉樹
二叉樹的性質、
-
若規定根節點的層次爲1,則一棵非空二叉樹第i層上最多有2^(i-1)(i>=1)個結點
-
若規定只有根節點的二叉樹的深度爲1,則深度爲K的二叉樹的最大結點數是2^k-1 (k>=0)
-
對任何一棵二叉樹,若是其葉結點個數爲n0,度爲2的非葉結點個數爲n2,則有n0 = n2+1
-
具備n個結點的徹底二叉樹,若是按照從上至下從左到右的順序對全部結點從0開始編號,則對於序號爲i的結點有:
- 若是i>0,則序號爲i的結點的雙親結點的序號爲(i-1)/2,若是i==0,則序號爲i的結點爲根節點,無雙親結點
- 若是2i+1<n,則序號爲i的雙親結點的左孩子序號是(i-1)/2,若是(2i+1)>=n,則序號爲i結點無右孩子結點
- 若是2i+2<n,則序號爲i結點的右孩子結點的序號爲2i+2,若是2i+2>=n,則序號爲i結點無右孩子結點
二叉樹的存儲結構
二叉樹的基本操做
-
二叉樹的建立
-
二叉樹的遍歷
-
前序
-
中序
-
後序
-
層序
-
初始化一個隊列
-
把根節點的指針入隊列
-
當隊列非空時循環執行
- 出隊列取一個節點
- 若該結點的左子樹非空,將該節點的左子樹指針入隊列
- 若該節點的右子樹非空將該節點的右子樹入隊列
-
結束
線索化二叉樹
線索化概念
普通二叉樹可能存在的問題
- 遞歸遍歷有可能致使棧溢出
- 非遞歸版本可能會下降程序的效率
- 想要找到某種遍歷形式下某個節點的前驅仍是後繼比較難
- 樹中有大量的空指針域形成浪費,
線索化過程
- 當某結點的左指爲空時,令該指針指向按照某種方式遍歷二叉樹時獲得該結點的前驅節點
- 當某結點的右指針爲空時,令該指針指向按照某種遍歷方式遍歷二叉樹時獲得該結點的後繼結點
線索標誌位
-
做用區分是孩子結點仍是前驅或者後繼
-
leftThread
-
rightThread
線索
線索二叉樹
對二叉樹按照某種方式(前序、中序、後序)遍歷使其稱爲線索二叉樹的過程稱爲按照什麼方法對二叉樹進行線索化
堆
堆的概念
- 把全部的元素按照徹底二叉樹的方式存儲在一個一維數組中並知足Ki<=K2i+1且Ki<=K2i+2(Ki>=K2i+1且Ki>=K2i+2),這個堆稱爲最小堆(最大堆)
堆的分類
-
小堆
- 任一節點的關鍵碼均小於它左右孩子的關鍵碼,位於堆頂結點的關鍵碼最小
-
大堆
- 任一結點的關鍵碼均大於它左右孩子的關鍵碼,位於堆頂結點的關鍵碼最大
堆的性質
- 若是i=0,結點i是根結點,沒有雙親結點,不然結點i的雙親結點爲(i-1)/2
- 若是2i+1>n-1,則結點i無左孩子,不然結點i的左孩子爲節點2i+1
- 若是2i+1>n-1,則結點i無左孩子,不然結點i的左孩子爲節點2i+2
堆的建立
堆的插入
堆的刪除
堆的應用
Huffman樹
概念
- 路徑
- 路徑長度
- 把帶權路徑長度最小的樹叫作Huffman樹
構造huffman樹
huffman編碼
-
編碼
- 在數據通訊中常常把傳輸的文字轉換成二進制字符0和1組成的二進制串,這叫作編碼
- 等長編碼
- 不等長編碼
文件壓縮
二叉搜索樹
性質
- 若是左子樹不爲空,則左子樹上全部節點的值都小於根結點的值
- 它的右子樹不爲空,則右子樹上全部節點的值都大於根結點的值
- 它的左右子樹也分別爲二叉搜索樹
操做
-
搜索
-
若根結點不爲空
- 根結點key==要查找的key,返回true
- 根結點key>查找key,在其左子樹查找
- 根結點key<查找key,在其右子樹查找
- 不然返回false
-
插入
- 首先檢測這個節點是否是已經存在,要是存在不插入
- 不然將元素插入到找到的位置
-
刪除
-
首先判斷是否在樹中,沒有直接返回
-
有的狀況
-
要刪除的節點沒有孩子節點
-
要刪除的節點只有左孩子
- 刪除該結點並使被刪除結點的雙親結點指向被刪除結點的左孩子結點
-
要刪除的節點只有右孩子
- 刪除該結點並使被刪除結點的雙親結點指向被刪除結點的右孩子結點
-
要刪除的節點有左、右孩子結點
- 在它的右子樹中尋找中序下的第一個結點(關鍵碼最小),用它的值填補到被刪除節點中,再來處理該結點的刪除問題
-
二叉搜索樹性能分析
- 最壞狀況下,平均查找長度爲O(n)通常狀況下平均長度爲O(lgn)
AVL樹
AVL樹性質
- 它的左右子樹都是AVL樹
- 左子樹和右子樹高度之差(簡稱平衡因子)的絕對值不超過1(-一、0、1)
- 若是一棵樹是高度平衡的,它就是AVL樹。若是它有n個節點,其高度可保持在0(lgn),平均搜索複雜度O(lgn)
平衡化旋轉
AVL樹的插入
- 若是是空樹,插入後即爲根結點,插入後直接返回true
- 若是樹不空,尋找插入位置,若在查找過程當中找到key,則插入失敗直接返回false
- 插入節點
- 更新平衡因子,對樹進行調整
AVL樹的刪除
-
被刪除結點只有左孩子
- parent的平衡因子爲1或者-1,parent高度不變,則從parent到根全部結點高度均不變,不用調整
-
被刪除結點只有右孩子
- parent的平衡因子變成0,雖然以parent爲根的子樹平衡,其高度減1,但須要檢查parent的雙親結點的平衡性
-
被刪除結點左右孩子都有
-
變爲刪除中序遍歷下的第一個結點q
- 結點parent的平衡因子爲2或者-2,則較矮子數縮短,parent發生不平衡,須要進行平衡化旋轉
-
parent較高子樹的根爲q
- 若是q的平衡因子爲0,執行單循環恢復parent
- 若是q的平衡因子與parent平衡因子(正負)號相同,則執行一個單循環恢復parent
- 若是q的平衡因子與parent平衡因子(正負)號相反,則執行一個雙旋轉恢復parent
紅黑樹
概念
- 紅黑樹是一棵二叉搜索樹,它在每一個節點上增長了一個存儲位來表示結點的顏色,保證最長路徑不超過最短路徑的兩倍,近似平衡
性質
- 每一個結點不是紅色就是黑色
- 樹的根結點是黑色
- 若是一個結點是紅色的,則它的兩個孩子結點是黑色的(沒有連續的兩個紅色結點)
- 對於每一個節點,從該結點到其全部後代葉節點的簡單路徑上,均包含相同數目的黑色結點(每條路徑上黑色結點的數量相等)
- 每一個葉子節點都是黑色的(此處的葉子結點指的是空節點)
插入實現
- 若樹爲空,插入後需將新節點改爲黑色
- 插入結點的父節點爲黑色,不違反任何性質,直接插入
- 狀況三
- 狀況四
- 狀況五
刪除
運用
- C++STL庫--map/set multimap multiset
- Java庫
- linux 內核
- 其餘一些庫
紅黑樹和AVL樹的比較
B樹
平衡的多叉樹
性質
- 根結點至少有兩個孩子
- 每一個非根結點至少有M/2(上取整)個孩子,至多有M個孩子
- 每一個非根結點至少有M/2-1(上取整)個關鍵字,而且以升序排列
- key[i]和key[i+1]之間的孩子結點的值介於key[i]、key[i+1]之間
- 全部的葉子結點都在同一層
B+樹
-
性質
- 其定義基本與B樹相同
- 非葉子節點的子樹指針與關鍵字個數相同
- 非葉子結點的子樹指針P[i],指向關鍵字值屬於[k[i],k[i+1])的子樹
- 爲全部葉子節點增長一個鏈指針
- 全部關鍵字都在葉子節點出現
-
搜索
-
特性
- 全部關鍵字都出如今葉子節點的鏈表中(稠密索引),且鏈表中的關鍵字剛好是有序的
- 不可能在葉子結點命中
- 非葉子節點至關因而葉子結點的索引(稀疏索引),葉子結點至關因而存儲(關鍵字)數據的數據層
- 更適合文件索引系統
B*樹
- 在B+樹的非根和非葉子結點之間再增長指向兄弟的指針
- 子主題 2
哈希
搜索(檢索)
查找
-
靜態查找
-
動態查找
-
哈希查找
-
哈希衝突
- 對於兩個數據Ki和Kj(i!=j),Ki!=Kj,可是有Hash(Ki)==Hash(Kj)
-
散列函數
- 哈希函數的定義域必須包括須要存儲的所有關鍵碼,而若是散列表容許有m個地址時,其值域必須在0-m-1之間
- 哈希函數計算出來的地址能均勻的分佈在整個空間中
- 哈希函數應該比較簡單
-
常見哈希函數
-
直接定址法
-
取關鍵字的某個線性函數爲散列地址
- 優勢:簡單均勻
- 缺點:須要事先直到關鍵字的分佈狀況
-
使用場景:適合查找比較小且連續的狀況
-
除留餘數法
- 設散列中容許的地址數爲m,取一個不大於m,但最接近或者等於m的質數p做爲除數,按照哈希函數:Hash(key)=key%p,p<=m;將關鍵碼轉換成哈希地址
-
平方取中法
- 假設關鍵字是1234,平方就是1522756,再抽取中間的三位數227做爲散列地址
-
摺疊法
- 將關鍵字從左到右分紅位數相等的幾部分,而後將這幾部分疊加求和,並按散列表長,取後幾位做爲散列地址
-
隨機數法
- 選擇一個隨機函數,取關鍵字的隨機函數值爲它的哈希地址
-
數學分析法
- 設有n個d位數,每一位肯能有r種不一樣的符號,這r種不一樣的符號在各位上出現的頻率不必定相同,可能在某些位上分佈比較均勻,可將分佈均勻的幾位根據開散列的方式做爲散列地址
散列衝突處理方法
-
閉散列法
-
開散列法
- 首先對關鍵碼集合用散列函數計算散列地址,具備相同地址的關鍵碼歸於同一子集合,每一個子集合稱爲一個桶,各個桶中的元素經過一個單鏈表連接起來,各鏈表的頭結點組成一個向量,向量的元素個數與可能的桶數相同
布隆過濾器
- 當一個元素被加入集合時,經過k個散列函數將這個元素映射成一個位數組中的k個點,將它們置爲1,檢索時只要看是否是都是1,就能夠,只要有一個零就不是,全是1,多是
排序
概念
排序算法的穩定性
- 兩個元素R[i]R[j],它們排序碼K[i]==K[j],且在排序以前,元素R[i]在R[j]以前,元素在R[i]和R[j]的順序不變
常見排序算法
-
插入排序
-
直接插入排序
- 插入到已排序序列中,先找位置,而後將位置以後得元素後移
- 穩定
-
希爾排序
-
選擇排序
-
選擇排序
-
每次把最小的元素換在最前面
-
錦標賽排序
- 一直兩兩比較找出獲勝者,將這個再也不比較,其餘繼續兩兩比較,取得獲勝者,一直循環
-
不穩定
-
堆排序
-
交換排序
-
冒泡排序
-
快速排序
- 取一個基準值將比它小得放在左側,大的放在右側。左右兩部分遞歸取基準值繼續分
-
歸併排序
-
歸併排序
- 將待排序的序列分紅兩個等長的子序列,而後將它們合併成一個序列
-
非比較排序
圖
由頂點集合及頂點間關係組成的一種數據結構
頂點和邊
圖的分類
-
有向圖
- 在有向圖中,頂點對<x,y>是有序的<x,y><y,x>是不一樣的兩條邊
-
無向圖
徹底圖
- 在有n個頂點的無向圖中,如有n*(n-1)/2條邊,即任意兩個兩個頂點之間有且只有一條邊
- 在n個頂點的有向圖中,如有n*(n-1)條邊,即任意兩個頂點之間有且僅有方向相反的邊
鄰接結點
- 在無向圖中G中,若(u,v)是E(G)中的一條邊,則稱u和v互爲鄰接頂點,並稱(u,v)依附於頂點u和v
- 在有向圖G中,若<u,v>是E(G)中的一條邊,則稱頂點u鄰接到v,頂點v鄰接自頂點u,並稱邊<u,v>與頂點u和v相關聯
頂點的度
-
與它相關聯的邊的條數
- 在有向圖中,頂點的度等於該頂點的入度與出度之和,其中頂點v的入度是以v爲終點的有向邊的條數,記作indev(v)頂點v的出度是以v爲起始點的有向邊的條數記作outdev(v)
- 無向圖的度等於入度和出度 dev(v) = indev(v) = outdev(v)
路徑
- 在圖G=(V,E)中,若從頂點vi出發有一組邊使其可到達頂點vj,則稱頂點vi到vj的頂點序列爲從頂點vi到頂點vj的路徑
權
路徑長度
- 對於不帶權的圖,一條邊的路徑長度是指該路徑上的邊的條數
- 對於帶權的圖,一條路徑的長度是指一條路徑的路徑長度是指該路徑上各個邊權值的總和
簡單路徑與迴路
- 如路徑上各個頂點 均不重複,則稱這樣的路徑是簡單路徑,若路徑上第一個頂點v1和最後一個頂點vm重合,則稱這樣的路徑爲迴路或環
子圖
- 設圖G={V,E}和圖G1={V1.E1},若V1屬於V且E1屬於E,則稱G1是G的子圖
連通圖
- 無向圖中,兩個頂點之間有路徑就是連通的,任一對頂點之間都是連通的則稱這個圖是連通圖
強連通圖
- 在有向圖中,任意一對頂點vi和vj之間都存在一條從vi到vj的路徑,也存在一條從vj到vi的一條路徑
生成樹
- 一個連通圖的最小連通子圖稱做該圖的生成樹,有n個頂點的連通圖的生成樹有n個頂點和n-1條邊
圖的存儲結構
圖的遍歷
連通份量
- 當無向圖爲非連通圖時,從圖中某一頂點出發,利用深度優先搜索或廣度優先搜索算法沒法遍歷圖的全部頂點,而只能訪問到該節點所在的最大連通子圖的全部頂點,這些頂點構成一個連通份量
最小生成樹
-
準則
- 只能使用圖中的邊來構造最小生成樹
- 只能使用剛好n-1條邊來鏈接圖中的n個頂點
- 選用的n-1條邊不能構成迴路
貪心算法
- 在問題求解時,老是作出當前看起來最好的選擇,也就是局部最優解
Kruskal算法
- 每次找一條具備最短權值且再也不同一連通份量上的邊加入生成樹
prime算法
單元最短路徑
- 從在帶權圖的某一頂點出發,找出一條通往另外一個頂點的最短路徑,最短也便是沿路徑各邊的權值和最小