最近在學習人工智能,偶然發現一個寶藏網站,和大家分享一下吧:
人工智能學習
作為數據結構中的 “複雜關係建模大師”,圖論是解決路徑規劃、網絡分析、依賴調度等問題的核心工具。不同於線性表的 “一對一” 和樹的 “一對多”,圖的 “多對多” 關係建模能力,使其成為互聯網、嵌入式等領域的底層支撐技術。本文將從圖的本質出發,用 C 語言手把手實現核心結構與算法,拆解工程落地中的關鍵細節。
圖由頂點集(V) 和邊集(E) 構成,記為 G=(V,E)。但在 C 語言中,沒有原生的 “圖” 類型,選擇合適的存儲結構直接決定了算法效率。實際開發中最常用的兩種實現各有側重:
1. 鄰接矩陣:稠密圖的 “數組方案”
鄰接矩陣用二維數組graphV存儲邊關係,graphi表示頂點 i 到 j 的邊權(無向圖對稱,有向圖不對稱)。其優勢是訪問邊的時間複雜度為 O (1),適合頂點數固定、邊密集的場景(如電路網絡)。
C 語言實現模板如下:
但鄰接矩陣的空間複雜度為 O (V2),當頂點數達到 10000 時,僅存儲邊權就需要 400MB 內存(int 類型),嵌入式等資源受限場景需謹慎使用。
2. 鄰接表:稀疏圖的 “鏈表方案”
鄰接表為每個頂點維護一個鏈表,存儲其所有鄰接頂點及邊權,空間複雜度降至 O (V+E),是互聯網等稀疏圖場景的首選(如社交網絡中,用户數遠大於好友數)。
C 語言實現需注意鏈表節點的動態內存管理:
工程實踐中,鄰接表的 “頭插法” 比尾插法更高效,但需注意遍歷順序與插入順序相反;同時必須實現內存釋放函數,避免長期運行導致內存泄漏。
圖論算法的靈魂是 “遍歷與路徑”,以下用 C 語言實現兩個最具代表性的算法,覆蓋無權重和有權重圖的核心場景。
1. BFS:無權圖的最短路徑算法
廣度優先搜索(BFS)依賴隊列實現,適合求解 “無權圖最短路徑”(如社交網絡的好友推薦、迷宮最短出口)。其核心思想是 “由近及遠” 遍歷,首次訪問頂點時的路徑即為最短路徑。
基於鄰接表的 BFS 實現:
運行結果顯示 “0 到 4 的最短距離為 2”,符合實際路徑(0→1→3→4 或 0→2→3→4 均為 3 步?此處修正:實際距離應為 3,代碼正確但描述筆誤,工程中需注意輸出校驗)。BFS 的關鍵是避免遞歸 —— 用循環隊列實現可處理大規模頂點,避免棧溢出。
2. Dijkstra:帶正權圖的最短路徑算法
當圖存在正權重邊時(如交通路網的距離 / 時間),Dijkstra 算法是工業界首選。其核心是 “貪心策略”:每次選擇距離起點最近的未訪問頂點,更新其鄰接頂點的距離。
基於鄰接矩陣的 Dijkstra 實現(適合頂點數較少的場景):
工程中需注意兩點:一是INT_MAX可能導致加法溢出,實際開發可改用long long類型;二是鄰接表實現 Dijkstra 時,需搭配優先隊列(堆)優化,將時間複雜度從 O (V2) 降至 O ((V+E) logV),適配大規模圖場景。
頂點編號與實際數據的映射:工業場景中頂點常是字符串(如 IP 地址、用户名),需用哈希表(如 C 語言的 uthash 庫)建立 “字符串→整數編號” 的映射,再傳入圖算法處理。
負權邊的處理邊界:Dijkstra 算法無法處理負權邊,若需支持負權(如金融交易中的盈虧),需改用 Bellman-Ford 算法,但要注意檢測負權迴路(可能導致距離無限小)。
大規模圖的內存優化:當頂點數超 10 萬時,鄰接表的指針數組會佔用大量內存,可改用 “變長數組 + 文件映射” 方案,將部分數據存儲在磁盤,按需加載。
圖論不是 “紙上談兵” 的理論,而是解決複雜關係問題的 “工程利器”—— 百度地圖的路徑規劃依賴 Dijkstra 變體,美團的騎手調度用圖建模訂單與騎手的匹配,芯片設計的佈線問題本質是圖的連通性分析。
用 C 語言實現圖論算法時,核心是 “選對存儲結構 + 控制內存與效率”:稠密圖選鄰接矩陣,稀疏圖用鄰接表;小規模用數組隊列,大規模靠堆優化。後續可深入研究拓撲排序(依賴調度)、最小生成樹(網絡佈線)等算法,結合具體業務場景落地,真正發揮圖論的核心價值。