圖及其相關算法

圖論/樹算法總參考:
https://www.bilibili.com/video/BV1BJ411e79i?from=search&seid=736566991405891381&rt=V%2FymTlOu4ow%2Fy4xxNWPUZ9JZcKWNbG1VEA96%2B1r70Cc%3D
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
頂點類型即 圖存儲的是什麼類型的數據
鄰接矩陣 的類型 即 權重

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
概念遞增關係: 無向圖(邊edge)-- 有向圖(Arc弧,出度入度Degree)–網network(權weight)
頂點vertex
頂點到頂點: path
在這裏插入圖片描述
正無窮表示有邊,但沒有權值, 因爲有些權值可以是 負值或0
正數表示 權值 且 兩頂點間有邊
零表示兩頂點間 沒有邊
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
圖的兩個核心就是: 頂點 , 弧(邊)
1.一維矩陣存儲頂點值,鄰接矩陣表示弧(有沒有,方向,權值) 方向:橫着看
2.鄰接表即 數組 + 鏈表。
數組存儲自定義的一個結構體: 頂點值+指向邊表的指針
鏈表存儲一個頂點的所有鄰接點的下標(有沒有弧,方向,權值)

方向:以頂點爲弧尾來建立鄰接表
在這裏插入圖片描述
在這裏插入圖片描述
方向: 一般將頂點作爲弧尾來明確方向,容易得到某個頂點的出度(outdegree)。 如果想知道某表的入度(indegree),就將頂點作爲弧頭來明確方向,建立逆鄰接表。

鄰接表與逆鄰接表結合, 就是十字鏈表。 可以同時表示出度和入度
在這裏插入圖片描述
深度優先搜索的步驟分爲 1.固定一個方向遞進下去 2.回溯上來。
顧名思義,深度優先,則是以深度爲準則,先一條路走到底,直到達到目標。這裏稱之爲遞歸下去。
否則既沒有達到目標又無路可走了,那麼則退回到上一步的狀態,走其他路。這便是回溯上來。(右手原則) 右手原則指的是自己代入迷宮的 第一視角,面對岔路口只走最右手

引入一套機制:
在這裏插入圖片描述
引入一個棧,來記錄走過的節點,從而實現回溯
引入 wihte, grey ,black 三種顏色表示 頂點的狀態。
white: 沒有走過的點, grey: 走過的點,但這個點還有白色臨接點(即可回溯的點),
black: 走過且鄰接點都走過, 即路的盡頭

在這裏插入圖片描述
在這裏插入圖片描述
廣度優先遍歷:
一層層的向外延伸, 一次只延伸一層節點。
引入隊列機制: 記錄即將訪問的節點
1 創建一個隊列,遍歷的起始點放入隊列
2 從隊列中取出一個元素,打印它,並將其未訪問過的子結點放到隊列中
3 重複2,直至隊列空
在這裏插入圖片描述
在這裏插入圖片描述
然後用一個數組來接收出棧的節點, 從而記錄每個節點完成遍歷
在這裏插入圖片描述
樹的遍歷就是遞歸的進行 根左右,左根右,左右根的訪問
所謂遍歷就是:大樹化小樹,小樹化元素。 左根右 指的是 左子樹,根,右子樹
在這裏插入圖片描述
前序遍歷就是右手原則的深度優先遍歷 右手走到底, 沒路了再回來走左手
在這裏插入圖片描述
在這裏插入圖片描述

在這裏插入圖片描述
在這裏插入圖片描述
經典題: 給前中後序遍歷順序, 請重構樹
1.必須給中序,否則無法重構。 所以只有 前中, 後中 兩種情況
2. 前序的意義就是有第一個節點, 中序的意義就是劃分左右子樹
在這裏插入圖片描述
即通過前,後序遍歷來找 子樹的根節點, 然後帶入中序判斷

在有向圖中,可能需要執行多次DFS才能遍歷整個圖(一個起始點走沒了,再換個起始點)
在這裏插入圖片描述

最小生成樹: 解決權值和最小問題
連通圖: 圖中從一個頂點可以到達任意一頂點(至少有一條路) n個頂點時,至少有n-1個邊
完全圖: 圖中的任何兩個點都可以直接連通 , n個頂點時,有n(n − 1) / 2條邊
生成樹:能連通所有頂點而又不產生迴路的任何子圖都是圖的生成樹
樹一般來說是基於圖而生的,而樹是一種特殊的圖:無環連通圖。

解決問題: 路段建設的費用不同(權值),市長連通所有村要花費的最小費用
https://www.bilibili.com/video/BV1EJ411S7A2
1.Kruscal算法:在不構成環的前提下,一直取圖中的最小邊(以邊爲導向)
2.Prim算法:在不構成環的前提下,一直找離最小生成樹最近的點並接入最小生成樹(以點爲導向),每次只能取一個點和一個邊
在這裏插入圖片描述
兩者比較: 最終的結果肯定是相同的
Prim算法是直接查找,多次尋找鄰邊的權重最小值,而Kruskal是需要先對權重排序後查找的
Kruskal在算法效率上是比Prim快的,因爲Kruskal只需一次對權重的排序就能找到最小生成樹,而Prim算法需要多次對鄰邊排序才能找到

邊比較少時(邊比點少),用Kruscal算法
點少時,用prim算法

最短路徑算法:

Dijkstra(迪傑斯特拉),是貪心算法的一個應用
https://www.youtube.com/watch?v=pVfj6mxhdMw
求從一個頂點出發,到任意一個點的最短路徑
1.選擇一個出發點,引入兩個序列: unvisited node{A,B,C,D} 記錄還沒有訪問過的點
distance{A:5 B: ∞ C:∞ D:∞} 記錄點到出發點的距離
2.通過廣度優先算法層層訪問頂點, 訪問後移出unvisit表,並將距離更新到distance表中

訪問已知距離中最近的點
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
選擇一個出發點,引入一個序列:unvisited node{A,B,C,D}
引入一個表,兩個屬性:起始點到各點的最短距離,最短路徑(A->D->E->C)

1.訪問距離起始點最近的點B
2.計算B點所有鄰接點到起始點A的距離(即起始點到B點的距離+B到鄰接點的距離)
3.與表中路徑比較, 如果比已知最短路徑更短, 更新路徑和距離
4.完成對B點的訪問,將B點移出unvisit序列
重複上述步驟
核心思想是基於已知的最短路徑,逐步比較出其他最短路徑。然後比較出了到每個點的最短路徑

在這裏插入圖片描述
想求A到H(明確的起點和終點)的最短路徑, 還是得把全圖走完比較完,才能確保A到H的最短路徑。過程同上

在這裏插入圖片描述

串就是存儲 char的 數組(或動態數組)。極其簡單
在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章