1. 程式人生 > >Python實現深度優先與寬度優先搜尋演算法

Python實現深度優先與寬度優先搜尋演算法

實驗目的:

瞭解和掌握深度優先和寬度優先演算法的原理以及應用並實現兩種演算法。

實驗內容:

1. 演算法原理

首先,我們給定一個二叉樹圖如下:

 

1). 寬度優先搜尋:

寬度優先搜尋演算法(Breadth First Search,BSF),思想是:

· 1.從圖中某頂點v出發,首先訪問定點v

· 2.在訪問了v之後依次訪問v的各個未曾訪問過的鄰接點;

· 3.然後分別從這些鄰接點出發依次訪問它們的鄰接點,並使得“先被訪問的頂點的鄰接點先於後被訪問的頂點的鄰接點被訪問;

· 4.直至圖中所有已被訪問的頂點的鄰接點都被訪問到;

· 5.如果此時圖中尚有頂點未被訪問,則需要另選一個未曾被訪問過的頂點作為新的起始點,重複上述過程,直至圖中所有頂點都被訪問到為止。

換句話說,廣度優先搜尋遍歷圖的過程是以v為起點,由近至遠,依次訪問和v有路徑相通且路 徑長度為1,2...的頂點。
如上圖的BFS訪問順序為:

A->B->C->D->E->F

2). 深度優先搜尋:

圖的深度優先搜尋(Depth First Search, DFS),和樹的前序遍歷非常類似。

它的思想:

1.從頂點v出發,首先訪問該頂點;

2.然後依次從它的各個未被訪問的鄰接點出發深度優先搜尋遍歷圖;

3.直至圖中所有和v有路徑相通的頂點都被訪問到。

4.若此時尚有其他頂點未被訪問到,則另選一個未被訪問的頂點作起始點,重複上述過程,直至圖中所有頂點都被訪問到為止

如上圖的BFS訪問順序為:

A->B->D->E->C->F

2. 關鍵程式碼的編寫

1)首先定義一個類,建立一個二叉樹圖

# 首先定義一個建立圖的類,使用鄰接矩陣
class Graph(object):
    def __init__(self, *args, **kwargs):
        self.order = []  # visited order
        self.neighbor = {}

    def add_node(self, node):
        key, val = node
        if not isinstance(val, list):
            print('節點輸入時應該為一個線性表')    # 避免不正確的輸入
        self.neighbor[key] = val

 

2)寬度優先演算法的實現

# 寬度優先演算法的實現
def BFS(self, root):
    #首先判斷根節點是否為空節點
    if root != None:
        search_queue = deque()
        search_queue.append(root)
        visited = []
    else:
        print('root is None')
        return -1

    while search_queue:
        person = search_queue.popleft()
        self.order.append(person)

        if (not person in visited) and (person in self.neighbor.keys()):
            search_queue += self.neighbor[person]
            visited.append(person)

 

3)深度優先演算法的實現

# 深度優先演算法的實現
def DFS(self, root):
    # 首先判斷根節點是否為空節點
    if root != None:
        search_queue = deque()
        search_queue.append(root)

        visited = []
    else:
        print('root is None')
        return -1

    while search_queue:
        person = search_queue.popleft()
        self.order.append(person)

        if (not person in visited) and (person in self.neighbor.keys()):
            tmp = self.neighbor[person]
            tmp.reverse()

            for index in tmp:
                search_queue.appendleft(index)

            visited.append(person)

 

3.執行結果的展示

 

實驗過程中遇到的問題如何解決的?

1. 遇到的問題

   在本次實驗中最大的問題就是對於兩個演算法的理解和實現吧,比如是迭代還是遞迴,還是回溯,都是我們值得去思考和理解的。

2. 如何解決

其實,把嚴蔚敏的資料結構裡面的原理理解清楚了,這兩個演算法其實不難的,如果這都理解不清楚,就說明資料結構學得很有問題,立即推放棄學計算機。

本次實驗的體會(結論)

本次實驗在很大層度上讓我進一步瞭解了這兩種演算法的區別和原理,不僅專業課學習上有一定幫助,同時也為考研複習提供了一個很好的複習。

日期:2018-06-12

附錄:

完整的程式碼:

# -*- coding: utf-8 -*-
# /usr/bin/python
# 作者:郭暢
# 實驗日期:20180612
# Python版本:3.6.4
# 主題:基於深度優先和寬度優先的搜尋演算法的簡單實現
# 參考書籍:資料結構C語言版(清華大學出版社嚴蔚敏版)

from collections import deque    # 線性表的模組

# 首先定義一個建立圖的類,使用鄰接矩陣
class Graph(object):
    def __init__(self, *args, **kwargs):
        self.order = []  # visited order
        self.neighbor = {}

    def add_node(self, node):
        key, val = node
        if not isinstance(val, list):
            print('節點輸入時應該為一個線性表')    # 避免不正確的輸入
        self.neighbor[key] = val

    # 寬度優先演算法的實現
    def BFS(self, root):
        #首先判斷根節點是否為空節點
        if root != None:
            search_queue = deque()
            search_queue.append(root)
            visited = []
        else:
            print('root is None')
            return -1

        while search_queue:
            person = search_queue.popleft()
            self.order.append(person)

            if (not person in visited) and (person in self.neighbor.keys()):
                search_queue += self.neighbor[person]
                visited.append(person)

    # 深度優先演算法的實現
    def DFS(self, root):
        # 首先判斷根節點是否為空節點
        if root != None:
            search_queue = deque()
            search_queue.append(root)

            visited = []
        else:
            print('root is None')
            return -1

        while search_queue:
            person = search_queue.popleft()
            self.order.append(person)

            if (not person in visited) and (person in self.neighbor.keys()):
                tmp = self.neighbor[person]
                tmp.reverse()

                for index in tmp:
                    search_queue.appendleft(index)

                visited.append(person)

    def clear(self):
        self.order = []

    def node_print(self):
        for index in self.order:
            print(index, end='  ')


if __name__ == '__main__':
    # 建立一個二叉樹圖
    g = Graph()
    g.add_node(('A', ['B', 'C']))
    g.add_node(('B', ['D', 'E']))
    g.add_node(('C', ['F']))

    # 進行寬度優先搜尋
    g.BFS('A')
    print('寬度優先搜尋:')
    print('  ', end='  ')
    g.node_print()
    g.clear()

    # 進行深度優先搜尋
    print('\n\n深度優先搜尋:')
    print('  ', end='  ')
    g.DFS('A')
    g.node_print()
    print()