Python實戰開發及案例分析(22)—— 深度優先

????????深度優先搜索(Depth-First Search, DFS)是一種用于遍歷或搜索樹或圖的算法。與廣度優先搜索不同,深度優先搜索盡可能深地遍歷圖的分支,直到找到目標或達到死胡同后才回溯。DFS可以使用遞歸實現或利用棧來進行非遞歸實現。

Python中的DFS實現

????????以下是使用Python實現深度優先搜索的兩種方式:遞歸和非遞歸(使用棧)。

圖的定義

????????首先,定義一個圖,這里使用字典來實現,其中鍵是節點,值是與該節點直接相連的節點列表。

graph = {'A': ['B', 'C'],'B': ['D', 'E'],'C': ['F'],'D': [],'E': ['G'],'F': [],'G': []
}
遞歸實現DFS

????????遞歸是實現DFS的一種直觀方式。

def dfs_recursive(graph, vertex, visited=None):if visited is None:visited = set()visited.add(vertex)print(vertex, end=' ')  # 處理節點,這里是打印節點for neighbor in graph[vertex]:if neighbor not in visited:dfs_recursive(graph, neighbor, visited)# 調用DFS函數
dfs_recursive(graph, 'A')
非遞歸實現DFS

????????非遞歸實現使用棧來模擬遞歸過程。

def dfs_iterative(graph, start):visited = set()stack = [start]while stack:vertex = stack.pop()if vertex not in visited:print(vertex, end=' ')visited.add(vertex)# 將鄰接節點逆序壓棧,以保持與遞歸版本相同的遍歷順序stack.extend(reversed(graph[vertex]))# 調用DFS函數
dfs_iterative(graph, 'A')

案例分析:迷宮尋路問題

????????假設有一個迷宮,表示為一個二維網格,其中1代表墻壁,0代表可通行區域。我們需要找到從起點到終點的路徑。

迷宮定義
maze = [[0, 1, 0, 0, 0],[0, 1, 0, 1, 0],[0, 0, 0, 0, 0],[0, 1, 1, 0, 0],[0, 0, 0, 0, 0]
]
DFS求解迷宮

????????使用DFS找到從左上角到右下角的一條路徑。

def dfs_maze(maze, start, goal):directions = [(0, 1), (1, 0), (0, -1), (-1, 0)]  # 可移動方向(右,下,左,上)stack = [(start, [start])]visited = set([start])while stack:(x, y), path = stack.pop()if (x, y) == goal:return pathfor dx, dy in directions:nx, ny = x + dx, y + dyif 0 <= nx < len(maze) and 0 <= ny < len(maze[0]) and maze[nx][ny] == 0 and (nx, ny) not in visited:visited.add((nx, ny))stack.append(((nx, ny), path + [(nx, ny)]))return None# 起點和終點
start_pos = (0, 0)
end_pos = (4, 4)
path = dfs_maze(maze, start_pos, end_pos)
print("Path from start to goal:", path)

總結

????????深度優先搜索是一種強大的搜索算法,適用于路徑尋找、解決方案空間探索等多種場景。通過遞歸或非遞歸的棧實現,DFS可以有效地探索所有可能的路徑直到找到解決方案或遍歷所有節點。其應用不僅限于理論問題,還廣泛適用于實際的編程和工程任務中。

????????繼續深入探討深度優先搜索(DFS)的進階應用,我們可以考慮其在解決圖中的連通性問題、拓撲排序、尋找強連通分量等方面的實用性。這些應用突出了DFS在更復雜圖結構問題中的效率和實用性。

圖中的連通性問題

????????DFS非常適用于檢查或發現圖中的所有連通分量。連通分量是一個無向圖中最大的連通子圖,其中任意兩個頂點都有路徑相連。

示例:發現所有連通分量
def dfs_connected_components(graph, start, visited):stack = [start]while stack:vertex = stack.pop()if vertex not in visited:visited.add(vertex)stack.extend(graph[vertex] - visited)return visiteddef find_connected_components(graph):visited = set()components = []for vertex in graph:if vertex not in visited:component = dfs_connected_components(graph, vertex, visited.copy())components.append(component)return components# 定義一個圖
graph = {'A': set(['B', 'C']),'B': set(['A', 'D']),'C': set(['A']),'D': set(['B']),'E': set(['F']),'F': set(['E']),
}components = find_connected_components(graph)
print("Connected components:", components)

????????在這個例子中,find_connected_components 函數利用 DFS 探索圖中的每個頂點,并標記已訪問的頂點,以發現并返回所有獨立的連通分量。

拓撲排序

????????拓撲排序是有向無環圖(DAG)的線性排序,其中每個節點出現在其所有直接后繼之前。DFS可以有效實現拓撲排序。

示例:使用DFS實現拓撲排序
def dfs_topological_sort(graph, start, visited, stack):visited.add(start)for neighbor in graph[start]:if neighbor not in visited:dfs_topological_sort(graph, neighbor, visited, stack)stack.append(start)def topological_sort(graph):visited = set()stack = []for vertex in graph:if vertex not in visited:dfs_topological_sort(graph, vertex, visited, stack)return stack[::-1]  # 返回反轉的棧# 定義一個DAG
dag = {'A': ['C'],'B': ['C', 'D'],'C': ['E'],'D': ['F'],'E': [],'F': []
}order = topological_sort(dag)
print("Topological Order:", order)

????????在這個例子中,topological_sort 利用DFS遍歷圖,保證所有節點的后繼節點都已經被放置到棧中,從而實現拓撲排序。

尋找強連通分量

????????強連通分量是有向圖中的最大子圖,其中任意兩個頂點都互相可達。利用DFS可以有效地找到圖中的所有強連通分量。

示例:使用Kosaraju算法找到強連通分量
def dfs_for_scc(graph, vertex, visited, stack):visited.add(vertex)for neighbor in graph[vertex]:if neighbor not in visited:dfs_for_scc(graph, neighbor, visited, stack)stack.append(vertex)def transpose_graph(graph):transposed = {v: [] for v in graph}for vertex in graph:for neighbor in graph[vertex]:transposed[neighbor].append(vertex)return transposeddef find_scc(graph):stack = []visited = set()# Fill vertices in stack according to their finishing timesfor vertex in graph:if vertex not in visited:dfs_for_scc(graph, vertex, visited, stack)# Transpose the graphtransposed = transpose_graph(graph)# The final DFS according to the order defined by the stackvisited.clear()scc = []while stack:vertex = stack.pop()if vertex not in visited:component_stack = []dfs_for_scc(transposed, vertex, visited, component_stack)scc.append(component_stack)return scc# 定義有向圖
directed_graph = {'A': ['B'],'B': ['C'],'C': ['A', 'D'],'D': ['E'],'E': ['F'],'F': ['D', 'G'],'G': []
}scc = find_scc(directed_graph)
print("Strongly connected components:", scc)

????????在這個示例中,使用Kosaraju算法的兩次DFS遍歷來找出所有的強連通分組。第一次DFS決定節點處理的順序,第二次DFS在圖的轉置上執行,發現強連通分量。

總結

????????DFS的這些高級應用展示了它在解決復雜圖結構問題方面的強大功能,無論是分析網絡的結構特性、排序問題還是分組問題,DFS都能提供高效的解決方案。通過適當的實現和優化,DFS可以幫助解決現實世界中的許多關鍵技術挑戰。

????????深入探討深度優先搜索(DFS)在更多領域中的高級應用,可以發現這種算法不僅適用于圖和樹的基本遍歷,還可以被擴展應用于解決更多復雜的問題,如解決組合問題、搜索算法優化、以及多維數據結構的探索等。以下是DFS在這些領域中的一些具體應用案例。

組合問題

????????在解決組合問題時,如求解子集、排列、組合等,DFS提供了一種系統地遍歷所有可能選擇的方法。

示例:求解所有子集

????????給定一個不含重復元素的整數數組,求所有可能的子集(冪集)。

def subsets(nums):result = []def dfs(index, path):result.append(path)for i in range(index, len(nums)):dfs(i + 1, path + [nums[i]])dfs(0, [])return resultnums = [1, 2, 3]
print("Subsets:", subsets(nums))

????????這個示例中,通過遞歸地探索每個元素包含或不包含的所有可能,系統地生成了數組的所有子集。

搜索算法優化

????????在某些搜索問題中,通過DFS結合剪枝策略,可以有效地減少搜索空間,優化算法性能。

示例:解數獨

????????使用DFS來填充數獨,同時在每步通過剪枝減少不必要的搜索。

def solveSudoku(board):def is_valid(x, y, n):for i in range(9):if board[i][y] == n or board[x][i] == n:return Falseif board[3 * (x // 3) + i // 3][3 * (y // 3) + i % 3] == n:return Falsereturn Truedef dfs():for i in range(9):for j in range(9):if board[i][j] == '.':for num in '123456789':if is_valid(i, j, num):board[i][j] = numif dfs():return Trueboard[i][j] = '.'return Falsereturn Truedfs()# 假設board已被初始化為一個具體的數獨問題
# solveSudoku(board)
# print("Solved Sudoku Board:", board)

????????在這個示例中,DFS遞歸地嘗試每個空格的所有可能數字,并通過有效性檢查剪枝。

多維數據結構的探索

????????DFS也可以應用于探索多維數據結構,比如在多維數組或矩陣中尋找特定模式或路徑。

示例:島嶼數量計算

????????給定一個由 '1'(陸地)和 '0'(水)組成的二維網格,計算網格中的島嶼數量。

def numIslands(grid):def dfs(x, y):if not (0 <= x < len(grid) and 0 <= y < len(grid[0]) and grid[x][y] == '1'):returngrid[x][y] = '0'for dx, dy in [(-1, 0), (1, 0), (0, -1), (0, 1)]:dfs(x + dx, y + dy)count = 0for i in range(len(grid)):for j in range(len(grid[0])):if grid[i][j] == '1':dfs(i, j)count += 1return count# grid = [...]
# print("Number of islands:", numIslands(grid))

????????這個示例中,通過DFS遍歷每塊陸地,并將與之相連的所有陸地標記為訪問過,從而計算出島嶼的總數。

總結

????????通過以上案例,我們可以看到DFS不僅在理論中應用廣泛,其在實際問題解決中的靈活性和強大功能也得到了充分展示。無論是組合問題的求解、復雜搜索任務的優化,還是復雜數據結構的深入探索,DFS都能提供有效的解決方案。這些高級應用表明,深度優先搜索是解決計算機科學問題中不可或缺的工具之一。

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

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

相關文章

量子計算機接入歐洲最快超算!芬蘭加快混合架構算法開發

內容來源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 文丨浪味仙 排版丨沛賢 深度好文&#xff1a;1900字丨7分鐘閱讀 摘要&#xff1a;芬蘭技術研究中心&#xff08;VTT&#xff09;與 CSC 展開合作&#xff0c;基于量子計算機超算架構進行算法開…

jspXMl標記語言基礎

1.打開命令框進入數據庫 打開eclipse創建需要連接的項目 粘貼驅動程序 查看驅動器 使用sql的包 int代表個 conlm代表列名 <%page import"java.sql.ResultSet"%> <%page import"java.sql.Statement"%> <%page import"java.sql.Connect…

蛋白聚乙二醇化修飾檢測試劑盒

蛋白多肽因其高生物活性、高特異性等優點備受藥物開發商和研究者的青睞。但分子量大、親水性強、穩定性差等劣勢限制了蛋白多肽在臨床上的應用&#xff0c;特別是蛋白多肽作為一種異源蛋白具有很強的免疫原性&#xff0c;容易被機體免疫系統識別并清除&#xff0c;導致藥物的血…

萬物皆可監控(shell腳本監控TIDB-DM和DSG同步狀態)

監控的方式有很多&#xff0c;常用的有zabbix和prometheus平臺&#xff0c;理論上都可以做到對有狀態服務的監控&#xff0c;因為我個人對這兩個監控平臺不是很熟悉&#xff0c;所以一般喜歡使用shell腳本來做監控&#xff1b; 純oracle 數據庫的監控推薦使用EMCC&#xff0c;…

前端面試題日常練-day12 【面試題】

題目 希望這些選擇題能夠幫助您進行前端面試的準備&#xff0c;答案在文末。 1. 在JavaScript中&#xff0c;以下哪個關鍵字用于聲明一個變量&#xff1f; a) letb) varc) constd) all of the above2. 下面哪個方法可以用于將一個字符串轉換為整數&#xff1f; a) toInteger(…

藍橋杯備戰15.完全二叉樹的權值

P8681 [藍橋杯 2019 省 AB] 完全二叉樹的權值 - 洛谷 | 計算機科學教育新生態 (luogu.com.cn) #include<bits/stdc.h> using namespace std; #define endl \n #define int long long const int N 2e510; int a[N]; signed main() {std::ios::sync_with_stdio(0),cin.ti…

C# Winform+Halcon結合標準視覺工具

介紹 winform與halcon結合標準化工具實例 軟件架構 軟件架構說明 基于NET6 WINFORMHALCON 實現標準化視覺檢測工具 集成相機通訊 集成PLC通訊 TCP等常見通訊 支持常見halcon算子 圖形采集blob分析高精度匹配顏色提取找幾何體二維碼提取OCR識別等等 。。。 安裝教程 …

【Kafka】2.深入理解Kafka事件流平臺及其核心概念

1.事件流(Event streaming) 事件流是人體中樞神經系統的數字化的等價物。它是構建“始終在線”世界的技術基礎&#xff0c;在這個世界中&#xff0c;企業越來越多地被定義為軟件化和自動化&#xff0c;而軟件的用戶本身也是軟件。 從技術上講&#xff0c;事件流是從數據庫、傳…

vue2 雙向數據綁定的實現及原理

Oject.defineProperty() 是 JavaScript 中用于定義或修改對象的屬性的方法&#xff0c;可以控制屬性的特性&#xff08;如可枚舉性、可配置性、可寫性等&#xff09; Object.defineProperty(obj, prop, descriptor) obj&#xff1a;要在其上定義屬性的對象。 prop&#xff1a;要…

P7222 [RC-04] 信息學競賽

文章目錄 題目[RC-04] 信息學競賽題目描述輸入格式輸出格式樣例 #1樣例輸入 #1樣例輸出 #1 提示 思路AC代碼 題目 [RC-04] 信息學競賽 題目描述 小 R 今天學習了余角有關的數學知識&#xff0c;請你幫幫他計算一個角的余角吧&#xff01; 一個角的余角的計算公式如下&#…

SHELL編程(一)

目錄 一、 Linux操作系統&#xff08;一&#xff09;內核與操作系統&#xff08;二&#xff09;操作系統的功能 二、Linux高級命令&#xff08;一&#xff09; 離線安裝 dpkg1. 安裝2. 使用3. 查看安裝詳細信息4. 安裝路徑5. 不完全刪除6. 完全刪除 &#xff08;二&#xff09;…

KNN算法用于回歸分析

生成數據集 from sklearn.datasets import make_regression import matplotlib.pyplot as plt# 生成特征數量為1&#xff0c; 噪音為50的數據集 X, y make_regression(n_features1, n_informative1, noise50, random_state8)# 散點圖 plt.scatter(X, y, c"orange",…

什么是TCP的粘包、拆包問題?

一、問題解析 TCP粘包和拆包問題是指在進行TCP通信時&#xff0c;因為TCP是面向流的&#xff0c;所以發送方在傳輸數據時可能會將多個小的數據包粘合在一起發送&#xff0c;而接收方則可能將這些數據包拆分成多個小的數據包進行接收&#xff0c;從而導致數據接收出現錯誤或者數…

uniapp swiper添加點擊切換 上一張 下一張

<view click"switchPrev"><text>上一張</text> </view> <view click"switchNext"><text>下一張</text> </view> <swiper class"swiper" circular :current"current"> data() {…

MySQL數據庫練習二

素材&#xff1a;表名&#xff1a;worker-- 表中字段均為中文&#xff0c;比如部門號、工資、職工號、參加工作等 CREATE TABLE worker (部門號 int(11) NOT NULL,職工號 int(11) NOT NULL,工作時間 date NOT NULL,工資 float(8,2) NOT NULL,政治面貌 varchar(10) NOT NULL DE…

歡樂釣魚大師攻略大全,新手釣魚入坑必備攻略!

《歡樂釣魚大師》是一款深受玩家喜愛的釣魚手游&#xff0c;在游戲中&#xff0c;玩家可以通過升級和更換魚竿來享受釣魚的樂趣&#xff0c;并有機會釣到各種稀有魚類。然而&#xff0c;很多玩家在闖關過程中遇到了不少困難。為了幫助大家更好地掌握游戲技巧&#xff0c;小編特…

4 軟件定義安全綜合:使用c/s模式進行控制器數據安全交互管理

在SDN三層結構中&#xff0c;我們通過OpenFlow 協議可以控制數據轉發設備的相關行為&#xff08;包括收集設備的信息&#xff09;&#xff0c;那么控制器上的數據能否通過應用層的程序進行管理調用呢&#xff1f; SDN&#xff08;軟件定義網絡&#xff09;的北向開發是指通過編…

ASUS Zenbook PE重裝系統后一直轉圈不斷重啟

問題描述&#xff1a; ASUS Zenbook PE重裝系統后一直轉圈不斷重啟 問題原因&#xff1a; RST驅動問題 解決辦法&#xff1a; 使用U盤安裝原版系統&#xff0c;安裝過程中&#xff0c;發現磁盤頁面沒有不識別硬盤&#xff0c;此時選擇加載驅動&#xff0c;加載RST驅動。一…

二進制搭建k8s

實驗環境&#xff1a; k8s集群master01:192.168.1.11 k8s集群master02:192.168.1.22 master虛擬ip&#xff1a;192.168.1.100 k8s集群node01:192.168.1.33 k8s集群node01:192.168.1.44 nginxkeepalive01&#xff08;master&#xff09;:192.168.1.55 nginxkeepalive02&a…

渲染農場是什么意思?瑞云渲染為你解答

渲染農場是一種通過集合多臺計算機的計算能力來加速圖像渲染過程的系統。它尤其適用于動畫、電影特效和高端視覺效果的制作&#xff0c;這些領域通常需要處理非常復雜和計算密集型的渲染任務。 渲染農場就是一大群電腦&#xff0c;他們一起可以快速渲染出漂亮的圖像。在做動畫片…