Python 鄰接表詳細實現指南

鄰接表是圖數據結構的一種高效表示方法,特別適合表示稀疏圖。下面我將用 Python 詳細講解鄰接表的多種實現方式、操作方法和實際應用。

一、鄰接表基礎概念

鄰接表的核心思想是為圖中的每個頂點維護一個列表,存儲與該頂點直接相連的所有鄰接頂點。

鄰接表 vs 鄰接矩陣

特性鄰接表鄰接矩陣
空間復雜度O(V+E)O(V2)
檢查兩頂點是否相鄰O(degree(V))O(1)
獲取所有鄰接點O(1)O(V)
添加邊O(1)O(1)
刪除邊O(degree(V))O(1)

二、Python 鄰接表實現方式

1. 基礎列表實現(無向圖)

class Graph:def __init__(self, num_vertices):self.num_vertices = num_verticesself.adj_list = [[] for _ in range(num_vertices)]def add_edge(self, u, v):"""添加無向邊 u-v"""self.adj_list[u].append(v)self.adj_list[v].append(u)def print_graph(self):for i in range(self.num_vertices):print(f"頂點 {i} 的鄰接點: {self.adj_list[i]}")# 使用示例
g = Graph(5)
g.add_edge(0, 1)
g.add_edge(0, 4)
g.add_edge(1, 2)
g.add_edge(1, 3)
g.add_edge(1, 4)
g.add_edge(2, 3)
g.add_edge(3, 4)
g.print_graph()

2. 使用 defaultdict(動態頂點)

 

python

復制

from collections import defaultdictclass Graph:def __init__(self):self.adj_list = defaultdict(list)def add_edge(self, u, v):"""添加無向邊 u-v"""self.adj_list[u].append(v)self.adj_list[v].append(u)def print_graph(self):for vertex in self.adj_list:print(f"頂點 {vertex} 的鄰接點: {self.adj_list[vertex]}")# 使用示例
g = Graph()
g.add_edge(0, 1)
g.add_edge(0, 4)
g.add_edge(1, 2)
g.add_edge(1, 3)
g.print_graph()

3. 加權圖實現

 

python

復制

from collections import defaultdictclass WeightedGraph:def __init__(self):self.adj_list = defaultdict(list)def add_edge(self, u, v, weight):"""添加加權無向邊 u-v"""self.adj_list[u].append((v, weight))self.adj_list[v].append((u, weight))def print_graph(self):for vertex in self.adj_list:connections = [f"{v}({w})" for v, w in self.adj_list[vertex]]print(f"頂點 {vertex} 的連接: {', '.join(connections)}")# 使用示例
wg = WeightedGraph()
wg.add_edge(0, 1, 4)
wg.add_edge(0, 2, 1)
wg.add_edge(1, 2, 2)
wg.add_edge(1, 3, 5)
wg.print_graph()

三、鄰接表的高級操作

1. 有向圖實現

 

python

復制

class DirectedGraph:def __init__(self, num_vertices):self.num_vertices = num_verticesself.adj_list = [[] for _ in range(num_vertices)]def add_edge(self, u, v):"""添加有向邊 u→v"""self.adj_list[u].append(v)def reverse(self):"""反轉圖中所有邊的方向"""reversed_graph = DirectedGraph(self.num_vertices)for u in range(self.num_vertices):for v in self.adj_list[u]:reversed_graph.add_edge(v, u)return reversed_graphdef print_graph(self):for i in range(self.num_vertices):print(f"頂點 {i} 指向: {self.adj_list[i]}")# 使用示例
dg = DirectedGraph(4)
dg.add_edge(0, 1)
dg.add_edge(0, 2)
dg.add_edge(1, 2)
dg.add_edge(2, 0)
dg.add_edge(2, 3)
dg.print_graph()

2. 刪除邊和頂點

 

python

復制

class AdvancedGraph:def __init__(self):self.adj_list = defaultdict(list)def add_edge(self, u, v):self.adj_list[u].append(v)self.adj_list[v].append(u)def remove_edge(self, u, v):"""刪除無向邊 u-v"""if v in self.adj_list[u]:self.adj_list[u].remove(v)self.adj_list[v].remove(u)def remove_vertex(self, u):"""刪除頂點及其所有邊"""for v in self.adj_list[u]:self.adj_list[v].remove(u)del self.adj_list[u]def print_graph(self):for vertex in self.adj_list:print(f"頂點 {vertex} 的鄰接點: {self.adj_list[vertex]}")# 使用示例
ag = AdvancedGraph()
ag.add_edge(0, 1)
ag.add_edge(0, 2)
ag.add_edge(1, 2)
ag.add_edge(2, 3)
print("原始圖:")
ag.print_graph()ag.remove_edge(1, 2)
print("\n刪除邊1-2后:")
ag.print_graph()ag.remove_vertex(2)
print("\n刪除頂點2后:")
ag.print_graph()

四、鄰接表的實際應用

1. 廣度優先搜索(BFS)

 

python

復制

from collections import dequedef bfs(graph, start):visited = set()queue = deque([start])visited.add(start)while queue:vertex = queue.popleft()print(vertex, end=" ")for neighbor in graph.adj_list[vertex]:if neighbor not in visited:visited.add(neighbor)queue.append(neighbor)# 使用示例
g = Graph(4)
g.add_edge(0, 1)
g.add_edge(0, 2)
g.add_edge(1, 2)
g.add_edge(2, 0)
g.add_edge(2, 3)
g.add_edge(3, 3)print("BFS遍歷從頂點2開始:")
bfs(g, 2)

2. 深度優先搜索(DFS)

 

python

復制

def dfs(graph, start, visited=None):if visited is None:visited = set()visited.add(start)print(start, end=" ")for neighbor in graph.adj_list[start]:if neighbor not in visited:dfs(graph, neighbor, visited)# 使用示例
print("\nDFS遍歷從頂點2開始:")
dfs(g, 2)

3. 檢測圖中是否有環

 

python

復制

def has_cycle(graph):visited = set()def dfs_util(vertex, parent):visited.add(vertex)for neighbor in graph.adj_list[vertex]:if neighbor not in visited:if dfs_util(neighbor, vertex):return Trueelif neighbor != parent:return Truereturn Falsefor vertex in graph.adj_list:if vertex not in visited:if dfs_util(vertex, -1):return Truereturn False# 使用示例
cycle_graph = Graph(3)
cycle_graph.add_edge(0, 1)
cycle_graph.add_edge(1, 2)
cycle_graph.add_edge(2, 0)no_cycle_graph = Graph(3)
no_cycle_graph.add_edge(0, 1)
no_cycle_graph.add_edge(1, 2)print("\n圖中是否有環:")
print("cycle_graph:", has_cycle(cycle_graph))
print("no_cycle_graph:", has_cycle(no_cycle_graph))

五、性能優化技巧

  1. ?使用集合代替列表?:如果需要頻繁檢查邊的存在性

     

    python

    復制

    self.adj_list = defaultdict(set)  # 使用集合存儲鄰接點
  2. ?預分配空間?:已知頂點數量時

     

    python

    復制

    self.adj_list = [None] * num_vertices
    for i in range(num_vertices):self.adj_list[i] = []
  3. ?使用更高效的數據結構?:如?array.array?或?numpy.ndarray?處理大型圖

  4. ?并行處理?:對大型圖的操作可以使用多線程/多進程

六、常見問題解答

?Q: 如何表示帶權重的有向圖???

A: 可以使用字典存儲權重信息:

 

python

復制

class WeightedDirectedGraph:def __init__(self):self.adj_list = defaultdict(list)def add_edge(self, u, v, weight):self.adj_list[u].append((v, weight))def print_graph(self):for vertex in self.adj_list:connections = [f"{v}({w})" for v, w in self.adj_list[vertex]]print(f"頂點 {vertex} 指向: {', '.join(connections)}")

?Q: 如何處理頂點不是整數的情況???

A: 可以使用字典映射:

 

python

復制

class NamedGraph:def __init__(self):self.adj_list = defaultdict(list)self.vertex_index = {}self.index_vertex = {}self.counter = 0def add_vertex(self, name):if name not in self.vertex_index:self.vertex_index[name] = self.counterself.index_vertex[self.counter] = nameself.counter += 1def add_edge(self, u_name, v_name):self.add_vertex(u_name)self.add_vertex(v_name)u = self.vertex_index[u_name]v = self.vertex_index[v_name]self.adj_list[u].append(v)self.adj_list[v].append(u)def print_graph(self):for i in range(self.counter):name = self.index_vertex[i]neighbors = [self.index_vertex[v] for v in self.adj_list[i]]print(f"頂點 {name} 的鄰接點: {neighbors}")

通過以上詳細的 Python 實現,你應該能夠全面掌握鄰接表的構建方法和各種操作技巧。根據你的具體應用場景,可以選擇最適合的實現方式。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/84606.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/84606.shtml
英文地址,請注明出處:http://en.pswp.cn/web/84606.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Nginx反向代理解決跨域問題詳解

Nginx反向代理解決跨域問題詳解 核心原理 Nginx反向代理解決跨域的核心思路是讓客戶端請求同域名下的接口,由Nginx將請求轉發到目標服務器,從而規避瀏覽器的同源策略限制。 客戶端(同源:www.domain.com)↓Nginx&…

單片機測ntc熱敏電阻的幾種方法

在單片機中測量NTC(負溫度系數)熱敏電阻的阻值,通常需要將其轉換為電壓或頻率信號,再通過單片機進行采集和處理。以下是幾種常見的方法及其詳細說明: 1. 分壓法(最常用)?? ??原理??&…

一套基于粒子群優化(PSO)算法的天線波束掃描MATLAB實現方案

以下是一套基于粒子群優化(PSO)算法的天線波束掃描MATLAB實現方案,包含完整代碼、數學原理和詳細注釋。該方案針對均勻線性陣列(ULA)的波束方向圖優化,通過調整陣元相位實現主瓣指向目標方向并抑制旁瓣。 %% 天線波束掃描的PSO算法實現 % 作者:DeepSeek % 創建日期:20…

增量學習ASAP的源碼剖析:如何實現人形的運動追蹤和全身控制(核心涉及HumanoidVerse中的agents模塊)

前言 過去一周,我司「七月在線」長沙分部的具身團隊在機械臂和人形上并行發力 關于機械臂 一方面,在IL和VLA的路線下,先后采集了抓杯子、桌面收納、插入耳機孔的數據,然后云端訓-本地5090推理 二方面,在RL的路線下&a…

計算機網絡學習筆記:應用層概述、動態主機配置協議DHCP

文章目錄 一、應用層概述1.1、C/S架構1.2、P2P架構 二、動態主機配置協議DHCP2.1、DHCP發現報文2.2、DHCP提供報文2.3、DHCP請求報文2.4、DHCP確認報文2.5、DHCP的續約與終止 總結 一、應用層概述 應用層位于計算機網絡結構的最上層,用于解決應用進程的交互以實現特…

為服務器SSH登錄增加2FA驗證

安裝NTP模塊并設置時區 安裝NTP模塊 一般的服務器NTP服務默認是不安裝的,需要安裝NTP模塊【7】并啟用。 運行以下指令檢查你的NTP模塊是否已啟用,已啟用則忽略安裝NTP模塊的內容 timedatectl 如果你的返回內容和以下圖片一樣,則表示NTP未…

AI大模型提示詞工程研究報告:長度與效果的辯證分析

一、核心問題:提示詞長度與模型性能的平衡 核心矛盾:提示詞長度增加 → 信息豐富度↑ & 準確性↑ ? 計算成本↑ & 響應延遲↑ 二、詳細機制分析 (一)長提示詞的優勢(實證數據支持) 案例類型短提…

HttpServletResponse源碼解析

Java Servlet API 中 HttpServletResponse 接口的源碼,這是 Java Web 開發中非常核心的一個接口,用于向客戶端(通常是瀏覽器)發送 HTTP 響應。 public interface HttpServletResponse extends ServletResponse {int SC_CONTINUE …

AI基礎概念

目錄 1、ASR和STT區別 2、流式輸出 定義 原理 應用場景 優點 缺點 3、Ollama 4、mindspore和deepseek r1 v3 5、DeepSeek R1/V3 用的哪個底層AI框架 6、HAI-LLM比tensorflow、pytorch還強么 1. 核心優勢對比 2. 性能表現 3. 適用場景 總結 7、openai用的什么底層…

ubuntu20.04速騰聚創airy驅動調試

1.下載相關資料 下載包括:速騰airy產品手冊.pdf、RSView(用于顯示激光雷達數據)、3d數模文件、 RS-LiDAR-16用戶手冊 以下鏈接進行下載 https://www.robosense.cn/resources 2.連接線路后通過Wireshark抓包后進行本地IP配置 2.1按照線路連…

Redis的大key和熱key如何解決

文章目錄 Redis大Key一、什么是Redis大Key二、大Key的產生原因三、大Key的影響四、大Key的解決方案1. 檢測大Key2. 解決方案(1) 數據拆分(2) 使用壓縮算法(3) 使用合適的數據結構(4) 設置合理的過期時間(5) 合理清理(6) 配置優化 五、預防措施總結 Redis熱key一、熱Key問題的本…

恒溫晶振與溫補晶振的區別

在電子設備領域,晶振如同精準的“心臟起搏器”,為電路提供穩定的時鐘信號。恒溫晶振(OCXO)和溫補晶振(TCXO)作為兩類重要的晶體振蕩器,在不同的應用場景中發揮著關鍵作用,它們的區別…

基于SpringBoot的在線考試智能監控系統設計與實現

目錄 一.🦁前言二.🦁開源代碼與組件使用情況說明三.🦁核心功能1. ?算法設計2. ?Java開發語言3. ?Vue.js框架4. ?部署項目 四.🦁演示效果1. 管理員模塊1.1 用戶管理 2. 教師模塊2.1 考試管理2.2 瀏覽試題列表2.3 添加試題2.4 成…

0基礎學Python系列【16】自動化郵件發送的終極教程:Python庫smtplib與email詳解

大家好,歡迎來到Python學習的第二站!?? Python自帶了一些超好用的模塊,可以讓你不必從頭寫代碼就能實現很多功能。比如數學計算、文件操作、網絡通信等。花姐會挑選常用的一些模塊來講解,確保你能在實際項目中用到。?? 本章要學什么? 接下來花姐會深入淺出的講解下面…

環衛車輛定位與監管:安心聯車輛監控管理平臺--科技賦能城市環境衛生管理

一、 引言 城市環境衛生是城市文明的重要標志,也是城市管理的重要內容。隨著城市化進程的加快,環衛作業范圍不斷擴大,環衛車輛數量不斷增加,傳統的管理模式已難以滿足現代化城市管理的需求。為提高環衛作業效率,加強環…

GIS 數據質檢:驗證 Geometry 有效性

前言 在GIS開發中,數據的幾何有效性直接影響分析結果的準確性。無效的幾何(如自相交、空洞或坐標錯誤)可能導致空間計算失敗或輸出偏差。無論是Shapefile、GeoJSON還是數據庫中的空間數據,幾何質檢都是數據處理中不可忽視的關鍵步…

AI大模型學習之基礎數學:高斯分布-AI大模型概率統計的基石

🧑 博主簡介:CSDN博客專家、CSDN平臺優質創作者,高級開發工程師,數學專業,10年以上C/C, C#, Java等多種編程語言開發經驗,擁有高級工程師證書;擅長C/C、C#等開發語言,熟悉Java常用開…

HarmonyOS性能優化——耗時操作減少

耗時操作減少 在應用開發中,避免主線程執行冗余和耗時操作至關重要。這可以降低主線程負載,提升UI響應速度。 避免主線程冗余操作 冗余操作是不必要的、重復執行且對程序功能無實質性貢獻的操作。這些操作浪費計算資源,降低程序運行效率&a…

emscripten 編譯 wasm 版本的 openssl

搭建emscripten環境【參考:https://emscripten.org/docs/getting_started/downloads.html】 下載openssl解壓復制到emsdk目錄 依次執行下列命令: cd emsdk #激活emsdk source ./emsdk_env.shcd opensslemconfigure ./Configure linux-x32 -no-asm -sta…

uniapp 實戰新聞頁面(一)

新聞系統 一、 創建項目 創建個人中心 page.json 配置 tabar "tabBar": {"color":"#666","selectedColor": "#31C27C","list": [{"text": "首頁","pagePath": "pages/inde…