自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Python 圖結(jié)構(gòu)與樹形數(shù)據(jù)處理的六種算法實(shí)現(xiàn)

開發(fā)
在Python中,圖和樹是一種非常重要的非線性數(shù)據(jù)結(jié)構(gòu)。簡單來說,圖是由節(jié)點(diǎn)(Node)和邊(Edge)組成的集合,而樹**是圖的一種特殊形式,具有層級關(guān)系。

一、圖結(jié)構(gòu)與樹形數(shù)據(jù)的基礎(chǔ)概念

在Python中,圖和樹是一種非常重要的非線性數(shù)據(jù)結(jié)構(gòu)。簡單來說,圖是由節(jié)點(diǎn)(Node)和邊(Edge)組成的集合,而樹**是圖的一種特殊形式,具有層級關(guān)系。

舉個(gè)例子:假設(shè)你有一個(gè)家族譜系,每個(gè)人是一個(gè)節(jié)點(diǎn),父子關(guān)系是邊,這就是一棵樹!再比如社交網(wǎng)絡(luò)中,人與人之間的朋友關(guān)系可以看作是一個(gè)圖。

樹的基本術(shù)語:

  • 根節(jié)點(diǎn)(Root):樹的起點(diǎn)。
  • 子節(jié)點(diǎn)(Child):某個(gè)節(jié)點(diǎn)的直接后繼。
  • 父節(jié)點(diǎn)(Parent):某個(gè)節(jié)點(diǎn)的直接前驅(qū)。
  • 葉子節(jié)點(diǎn)(Leaf):沒有子節(jié)點(diǎn)的節(jié)點(diǎn)。

下面用Python定義一個(gè)簡單的樹:

class TreeNode:
    def __init__(self, value):
        self.value = value  # 節(jié)點(diǎn)值
        self.children = []  # 子節(jié)點(diǎn)列表

# 創(chuàng)建樹
root = TreeNode("A")
child1 = TreeNode("B")
child2 = TreeNode("C")
root.children.append(child1)
root.children.append(child2)

# 打印樹結(jié)構(gòu)
def print_tree(node, level=0):
    print("  " * level + node.value)  # 按層級打印
    for child in node.children:
        print_tree(child, level + 1)

print_tree(root)

運(yùn)行結(jié)果:

A
  B
  C

是不是很簡單?接下來我們還會深入講解如何用算法處理這些結(jié)構(gòu)!

二、使用Python實(shí)現(xiàn)深度優(yōu)先搜索(DFS)算法

1. 什么是深度優(yōu)先搜索(DFS)

深度優(yōu)先搜索(DFS)是一種遍歷圖或樹的常用算法。它從起始節(jié)點(diǎn)開始,沿著一條路徑盡可能深入地探索,直到無法繼續(xù)為止,然后回溯到上一個(gè)節(jié)點(diǎn),重復(fù)這個(gè)過程。

舉個(gè)例子:想象你在一個(gè)迷宮里,總是選擇第一個(gè)路口一直走下去,直到走不通才返回之前的岔路口嘗試另一條路。

2. Python代碼實(shí)現(xiàn)DFS

我們可以用遞歸或者棧來實(shí)現(xiàn)DFS。下面是一個(gè)基于遞歸的簡單實(shí)現(xiàn):

# 定義圖結(jié)構(gòu)為字典形式
graph = {
    'A': ['B', 'C'],
    'B': ['A', 'D', 'E'],
    'C': ['A', 'F'],
    'D': ['B'],
    'E': ['B', 'F'],
    'F': ['C', 'E']
}

# 定義DFS函數(shù)
def dfs(graph, node, visited=None):
    if visited is None:  # 初始化訪問列表
        visited = set()
    visited.add(node)  # 標(biāo)記當(dāng)前節(jié)點(diǎn)為已訪問
    print(node, end=" ")  # 打印節(jié)點(diǎn)
    for neighbor in graph[node]:  # 遍歷相鄰節(jié)點(diǎn)
        if neighbor not in visited:  # 如果相鄰節(jié)點(diǎn)未訪問,則遞歸調(diào)用
            dfs(graph, neighbor, visited)

# 調(diào)用DFS函數(shù)
dfs(graph, 'A')

運(yùn)行結(jié)果:

A B D E F C

這段代碼展示了如何通過遞歸實(shí)現(xiàn)DFS,從節(jié)點(diǎn)'A'開始遍歷整個(gè)圖。每個(gè)節(jié)點(diǎn)只會被訪問一次,避免了無限循環(huán)的問題。

三、使用Python實(shí)現(xiàn)廣度優(yōu)先搜索(BFS)算法

1. 什么是廣度優(yōu)先搜索(BFS)

廣度優(yōu)先搜索(BFS)是一種用于圖或樹的遍歷算法,它從根節(jié)點(diǎn)開始,逐層訪問所有鄰居節(jié)點(diǎn)。比如,我們要找朋友的朋友列表,BFS就很適合!下面通過一個(gè)簡單的例子來演示。

from collections import deque

# 定義圖結(jié)構(gòu)
graph = {
    "你": ["Alice", "Bob", "Claire"],
    "Alice": ["Peggy"],
    "Bob": ["Anuj", "Peggy"],
    "Claire": ["Thom", "Jonny"]
}

def bfs(name):
    search_queue = deque()  # 創(chuàng)建隊(duì)列
    search_queue += graph[name]  # 將圖中的鄰居加入隊(duì)列
    searched = []  # 記錄已檢查過的人

    while search_queue:
        person = search_queue.popleft()  # 取出第一個(gè)人
        if person not in searched:  # 如果這個(gè)人沒被檢查過
            if person_is_seller(person):  # 檢查是否是銷售員
                print(f"{person} 是芒果銷售商!")
                return True
            else:
                search_queue += graph.get(person, [])  # 不是銷售商,將這個(gè)人的朋友加入隊(duì)列
                searched.append(person)  # 標(biāo)記為已檢查
    return False

def person_is_seller(name):
    return name[-1] == 'm'  # 假設(shè)名字以m結(jié)尾的是銷售商

bfs("你")  # 調(diào)用BFS函數(shù)

運(yùn)行結(jié)果可能為:

Thom 是芒果銷售商!

這段代碼展示了如何用BFS查找芒果銷售商。我們使用隊(duì)列保存需要檢查的人,并逐層擴(kuò)展搜索范圍,直到找到目標(biāo)!

四、理解并實(shí)現(xiàn)Dijkstra最短路徑算法

1. Dijkstra算法的基本原理

Dijkstra算法是用來解決單源最短路徑問題的經(jīng)典算法。它的核心思想是:從起點(diǎn)出發(fā),逐步找到離起點(diǎn)最近的節(jié)點(diǎn),并更新其他節(jié)點(diǎn)的距離。假設(shè)我們有一個(gè)圖,每個(gè)邊都有權(quán)重(表示距離),目標(biāo)是從起點(diǎn)到所有其他節(jié)點(diǎn)的最短路徑。

比如,想象一個(gè)城市地圖,你想知道從家到公司的最短路線。Dijkstra算法就能幫你完成!

import heapq

def dijkstra(graph, start):
    # 初始化距離字典,所有節(jié)點(diǎn)距離設(shè)為無窮大
    distances = {node: float('inf') for node in graph}
    distances[start] = 0  # 起點(diǎn)距離為0
    priority_queue = [(0, start)]  # 優(yōu)先隊(duì)列存儲(距離, 節(jié)點(diǎn))

    while priority_queue:
        current_distance, current_node = heapq.heappop(priority_queue)

        # 如果當(dāng)前距離大于記錄的距離,則跳過
        if current_distance > distances[current_node]:
            continue

        # 遍歷鄰居節(jié)點(diǎn)
        for neighbor, weight in graph[current_node].items():
            distance = current_distance + weight

            # 如果找到更短路徑,更新距離并加入隊(duì)列
            if distance < distances[neighbor]:
                distances[neighbor] = distance
                heapq.heappush(priority_queue, (distance, neighbor))

    return distances

# 示例圖結(jié)構(gòu)
graph = {
    'A': {'B': 1, 'C': 4},
    'B': {'A': 1, 'C': 2, 'D': 5},
    'C': {'A': 4, 'B': 2, 'D': 1},
    'D': {'B': 5, 'C': 1}
}

print(dijkstra(graph, 'A'))  # 輸出: {'A': 0, 'B': 1, 'C': 3, 'D': 4}

代碼解析:

  • graph 是一個(gè)字典,表示帶權(quán)圖。例如,'A': {'B': 1, 'C': 4} 表示從 A 到 B 的距離是 1,到 C 的距離是 4。
  • 使用優(yōu)先隊(duì)列(heapq 模塊)來確保每次處理的是當(dāng)前最短路徑的節(jié)點(diǎn)。
  • 遍歷鄰居節(jié)點(diǎn)時(shí),動態(tài)更新最短距離。

通過這段代碼,你可以輕松計(jì)算任意節(jié)點(diǎn)間的最短路徑!

五、使用Kruskal算法實(shí)現(xiàn)最小生成樹

1. Kruskal算法簡介

Kruskal算法是一種用來求解圖的最小生成樹的經(jīng)典算法。它的核心思想是:按照邊的權(quán)重從小到大排序,逐步選擇不形成環(huán)路的邊,直到所有頂點(diǎn)都被連接起來。比如,一個(gè)城市之間的道路網(wǎng)絡(luò),如何用最少的成本修建公路?這就是Kruskal算法能解決的問題!

# 示例代碼:Kruskal算法實(shí)現(xiàn)
class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))
    
    def find(self, x):
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]
    
    def union(self, x, y):
        rootX = self.find(x)
        rootY = self.find(y)
        if rootX != rootY:
            self.parent[rootX] = rootY

def kruskal(edges, n):
    edges.sort(key=lambda x: x[2])  # 按權(quán)重排序
    uf = UnionFind(n)
    mst = []
    for u, v, w in edges:
        if uf.find(u) != uf.find(v):  # 如果不形成環(huán)
            uf.union(u, v)
            mst.append((u, v, w))
    return mst

# 測試數(shù)據(jù)
edges = [(0, 1, 7), (0, 3, 5), (1, 2, 8), (1, 3, 9), (2, 3, 6), (3, 4, 4)]
n = 5
result = kruskal(edges, n)
print("最小生成樹的邊為:", result)

輸出結(jié)果:

最小生成樹的邊為: [(3, 4, 4), (0, 3, 5), (2, 3, 6), (0, 1, 7)]

這段代碼通過Union-Find結(jié)構(gòu)來檢測環(huán)路,確保每次添加的邊都不會導(dǎo)致圖中出現(xiàn)環(huán)。最終輸出的是一組邊,它們構(gòu)成了最小生成樹!是不是很神奇?

六、實(shí)現(xiàn)Topological排序處理有向無環(huán)圖(DAG)

1. Topological排序基礎(chǔ)

Topological排序是一種對有向無環(huán)圖(DAG)進(jìn)行線性排序的方法,確保每個(gè)節(jié)點(diǎn)都在其所有依賴節(jié)點(diǎn)之后。比如,課程安排中,先修課必須在選修課之前完成。

from collections import defaultdict, deque

# 構(gòu)建圖
graph = defaultdict(list)
edges = [(0, 1), (0, 2), (1, 3), (2, 3)]
for u, v in edges:
    graph[u].append(v)

# 計(jì)算入度
in_degree = {u: 0 for u in graph}
for u in graph:
    for v in graph[u]:
        in_degree[v] = in_degree.get(v, 0) + 1

# 拓?fù)渑判?queue = deque([u for u in in_degree if in_degree[u] == 0])
result = []
while queue:
    node = queue.popleft()
    result.append(node)
    for neighbor in graph[node]:
        in_degree[neighbor] -= 1
        if in_degree[neighbor] == 0:
            queue.append(neighbor)

print(result)  # 輸出:[0, 1, 2, 3]

這段代碼展示了如何通過BFS實(shí)現(xiàn)Topological排序。我們首先計(jì)算每個(gè)節(jié)點(diǎn)的入度,然后將入度為0的節(jié)點(diǎn)加入隊(duì)列,依次處理并更新入度。最后得到的結(jié)果就是一種合法的拓?fù)漤樞颍?/p>

七、實(shí)戰(zhàn)案例:社交網(wǎng)絡(luò)中好友關(guān)系的分析與推薦系統(tǒng)構(gòu)建

1. 社交網(wǎng)絡(luò)中的圖結(jié)構(gòu)表示

在社交網(wǎng)絡(luò)中,用戶和好友關(guān)系可以用圖結(jié)構(gòu)來表示。每個(gè)用戶是一個(gè)節(jié)點(diǎn),好友關(guān)系是邊。比如,小明和小紅是好友,就可以用一條邊連接他們。我們用Python字典來表示這個(gè)圖:

graph = {
    "小明": ["小紅", "小剛"],
    "小紅": ["小明", "小麗"],
    "小剛": ["小明"],
    "小麗": ["小紅"]
}

這段代碼展示了如何用字典存儲好友關(guān)系。

2. 使用DFS算法分析好友關(guān)系

深度優(yōu)先搜索(DFS)可以用來查找兩個(gè)用戶之間是否存在好友關(guān)系路徑。下面是一個(gè)簡單的實(shí)現(xiàn):

def dfs(graph, start, goal, visited=None):
    if visited is None:
        visited = set()
    visited.add(start)
    if start == goal:
        return True
    for neighbor in graph[start]:
        if neighbor not in visited:
            if dfs(graph, neighbor, goal, visited):
                return True
    return False

print(dfs(graph, "小明", "小麗"))  # 輸出: True

這段代碼通過遞歸遍歷圖,判斷“小明”和“小麗”是否有好友關(guān)系。

3. 使用BFS算法計(jì)算好友距離

廣度優(yōu)先搜索(BFS)可以幫助我們計(jì)算兩個(gè)用戶之間的最短好友關(guān)系距離。例如:

from collections import deque

def bfs(graph, start, goal):
    queue = deque([(start, 0)])
    visited = {start}
    while queue:
        node, dist = queue.popleft()
        if node == goal:
            return dist
        for neighbor in graph[node]:
            if neighbor not in visited:
                visited.add(neighbor)
                queue.append((neighbor, dist + 1))
    return -1

print(bfs(graph, "小明", "小麗"))  # 輸出: 2

這里使用隊(duì)列實(shí)現(xiàn)BFS,計(jì)算“小明”到“小麗”的好友距離為2。

4. 基于共同好友的推薦系統(tǒng)

我們可以根據(jù)用戶的共同好友數(shù)量來推薦新朋友。比如:

def recommend_friends(graph, user):
    friends = set(graph[user])
    candidates = {}
    for friend in friends:
        for f_of_f in graph[friend]:  # 遍歷好友的好友
            if f_of_f != user and f_of_f not in friends:
                candidates[f_of_f] = candidates.get(f_of_f, 0) + 1
    return sorted(candidates.items(), key=lambda x: x[1], reverse=True)

print(recommend_friends(graph, "小明"))  # 輸出: [('小麗', 1)]

這段代碼根據(jù)共同好友的數(shù)量推薦新朋友給“小明”。

以上就是利用圖結(jié)構(gòu)和樹形數(shù)據(jù)處理算法解決社交網(wǎng)絡(luò)問題的簡單示例!

責(zé)任編輯:趙寧寧 來源: 手把手PythonAI編程
相關(guān)推薦

2023-11-28 15:32:30

負(fù)載均衡算法

2024-10-09 17:22:20

Python

2024-11-20 15:24:49

2021-07-29 09:00:00

Python工具機(jī)器學(xué)習(xí)

2023-08-29 13:53:00

前端攔截HashMap

2024-01-22 08:53:00

策略任務(wù)RocketMQ

2022-05-24 10:43:02

延時(shí)消息分布式MQ

2024-02-26 11:12:33

定時(shí)任務(wù)線程

2010-06-13 11:28:39

UML序列圖

2011-03-31 14:53:13

數(shù)據(jù)中心節(jié)能

2024-12-18 16:19:51

2023-09-25 12:23:18

Python

2020-06-28 09:57:24

數(shù)據(jù)結(jié)構(gòu)算法

2009-12-16 14:55:44

ISDN路由故障

2024-08-26 15:01:40

Python

2025-02-06 07:54:14

Python開發(fā)

2023-05-10 13:58:13

服務(wù)限流系統(tǒng)

2021-12-10 13:08:31

數(shù)據(jù)倉庫BI數(shù)據(jù)存儲

2023-06-01 16:45:11

React開發(fā)JavaScript

2022-01-11 18:21:11

存儲技術(shù)數(shù)據(jù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號