【Python | 邊學邊敲邊記】第二次:深度&&廣度優先演算法

極簡XksA發表於2018-10-12


【Python | 邊學邊敲邊記】第二次:深度&&廣度優先演算法

一、前言

以後儘量每天更新一篇,也是自己的一個學習打卡!加油!今天給大家分享的是,Python裡深度/廣度優先演算法介紹及實現。

二、深度、廣度優先演算法簡介

1.深度優先搜尋(DepthFirstSearch)

深度優先搜尋的主要特徵就是,假設一個頂點有不少相鄰頂點,當我們搜尋到該頂點,我們對於它的相鄰頂點並不是現在就對所有都進行搜尋,而是對一個頂點繼續往後搜尋,直到某個頂點,他周圍的相鄰頂點都已經被訪問過了,這時他就可以返回,對它來的那個頂點的其餘頂點進行搜尋。
深度優先搜尋的實現可以利用遞迴很簡單地實現。

2.廣度優先搜尋(BreadthFirstSearch)

廣度優先搜尋相對於深度優先搜尋側重點不一樣,深度優先好比是一個人走迷宮,一次只能選定一條路走下去,而廣度優先搜尋好比是一次能夠有任意多個人,一次就走到和一個頂點相連的所有未訪問過的頂點,然後再從這些頂點出發,繼續這個過程。

具體實現的時候我們使用先進先出佇列來實現這個過程:

  1. 首先將起點加入佇列,然後將其出隊,把和起點相連的頂點加入佇列,

  2. 將隊首元素v出隊並標記他

  3. 將和v相連的未標記的元素加入佇列,然後繼續執行步驟2直到佇列為空

廣度優先搜尋的一個重要作用就是它能夠找出最短路徑,這個很好理解,因為廣度優先搜尋相當於每次從一個起點開始向所有可能的方向走一步,那麼第一次到達目的地的這個路徑一定是最短的,而到達了之後由於這個點已經被訪問過而不會再被訪問,這個路徑就不會被更改了。

三、看程式碼,邊學邊敲邊記深度優先、廣度優先演算法

1.遍歷二叉樹圖形

【Python | 邊學邊敲邊記】第二次:深度&&廣度優先演算法

2.深度優先、廣度優先遍歷模型


 1


'''

2 date : 2018.7.29
3 author : 極簡XksA
4 goal : 深度/廣度優先演算法
5 '''

6
7 # 深度優先: 根左右 遍歷
8 # 廣度優先: 層次遍歷,一層一層遍歷
9
10 # 深度優先: 根左右 遍歷 (遞迴實現)
11 def   depth_tree (tree_node) :
12      if  tree_node  is   not   None :
13         print(tree_node._data)
14          if  tree_node._left  is   not   None :
15              return  depth_tree(tree_node._left)   # 遞迴遍歷
16          if  tree_node._right  is   not   None :
17              return  depth_tree(tree_node._right)   # 遞迴遍歷
18
19 # 廣度優先: 層次遍歷,一層一層遍歷(佇列實現)
20 def   level_queue (root) :
21      if  root  is   None :
22          return
23     my_queue = []
24     node = root
25     my_queue.append(node)   # 根結點入佇列
26      while  my_queue:
27         node = my_queue.pop( # 出佇列
28         print(node.elem)    # 訪問結點
29          if  node.lchild  is   not   None :
30             my_queue.append(node.lchild)     # 入佇列
31          if  node.rchild  is   not   None :
32             my_queue.append(node.rchild)     # 入佇列
3.資料結構設計、遍歷程式碼

方法一:列表法



 1


# 樹的資料結構設計


2 # 1.列表法
3 # 簡述:列表裡包含三個元素:根結點、左結點、右結點
4 my_Tree = [
5      'D' # 根結點
6     [ 'B' ,
7      [ 'F' ,[],[]],
8      [ 'G' ,[ 'E' ,[],[]],[]]
9      ],   # 左子樹
10     [ 'C' ,
11      [],
12      [ 'A' ,[ 'H' ,[],[]],[]]
13      ]    # 右子樹
14 ]
15
16 # 列表操作函式
17 # pop() 函式用於移除列表中的一個元素(預設最後一個元素),並且返回該元素的值。
18 # insert() 函式用於將指定物件插入列表的指定位置,沒有返回值。
19
20 # 深度優先: 根左右 遍歷 (遞迴實現)
21 def   depth_tree (tree_node) :
22      if  tree_node:
23         print(tree_node[ ])
24          # 訪問左子樹
25          if  tree_node[ 1 ]:
26             depth_tree(tree_node[ 1 ])   # 遞迴遍歷
27          # 訪問右子樹
28          if  tree_node[ 2 ]:
29             depth_tree(tree_node[ 2 ])   # 遞迴遍歷        
30 depth_tree(my_Tree)
31 # result:
32 #            D B F G E C A H
33
34 # 廣度優先: 層次遍歷,一層一層遍歷(佇列實現)
35 def   level_queue (root) :
36      if   not  root:
37          return
38     my_queue = []
39     node = root
40     my_queue.append(node)   # 根結點入佇列
41      while  my_queue:
42         node = my_queue.pop( # 出佇列
43         print(node[ ])    # 訪問結點
44          if  node[ 1 ]:
45             my_queue.append(node[ 1 ])     # 入佇列
46          if  node[ 2 ]:
47             my_queue.append(node[ 2 ])     # 入佇列       
48 level_queue(my_Tree)
49 # result :
50 #           D B C F G A E H

方法二:構造類節點法



 1


#2.構造類


2 # Tree類,類變數root 為根結點,為str型別
3 # 類變數right/left 為左右節點,為Tree型,預設為空
4 class   Tree :
5     root =  ''
6     right =  None
7     left =  None
8      # 初始化類
9      def   __init__ (self,node) :
10         self.root = node
11
12      def   set_root (self,node) :
13         self.root = node
14
15      def   get_root (self) :
16          return  self.root
17
18 # 初始化樹
19 # 設定所有根結點
20 a = Tree( 'A' )
21 b = Tree( 'B' )
22 c = Tree( 'C' )
23 d = Tree( 'D' )
24 e = Tree( 'E' )
25 f = Tree( 'F' )
26 g = Tree( 'G' )
27 h = Tree( 'H' )
28 # 設定節點之間聯絡,生成樹
29 a.left = h
30 b.left = f
31 b.right = g
32 c.right = a
33 d.left = b
34 d.right = c
35 g.left = e
36
37 # 深度優先: 根左右 遍歷 (遞迴實現)
38 def   depth_tree (tree_node) :
39      if  tree_node  is   not   None :
40         print(tree_node.root)
41          if  tree_node.left  is   not   None :
42             depth_tree(tree_node.left)   # 遞迴遍歷
43          if  tree_node.right  is   not   None :
44             depth_tree(tree_node.right)   # 遞迴遍歷
45 depth_tree(d)   # 傳入根節點
46 # result:
47 #            D B F G E C A H
48
49 # 廣度優先: 層次遍歷,一層一層遍歷(佇列實現)
50 def   level_queue (root) :
51      if  root  is   None :
52          return
53     my_queue = []
54     node = root
55     my_queue.append(node)   # 根結點入佇列
56      while  my_queue:
57         node = my_queue.pop( # 出佇列
58         print(node.root)    # 訪問結點
59          if  node.left  is   not   None :
60             my_queue.append(node.left)     # 入佇列
61          if  node.right  is   not   None :
62             my_queue.append(node.right)     # 入佇列
63 level_queue(d)
64 # result :
65 #           D B C F G A E H

四、後言

可能大家會好奇,深度優先演算法、廣度優先演算法對爬蟲有什麼用,不用好奇,慢慢後面就會懂得了。提前透露:幾乎所有網站都有首頁、XXX、XXX、XXX…在每個分頁下,又有很多分頁,這樣所有url之間的聯絡實際上就可以比喻成一棵樹,當我們想要系統爬取時,為了不重複爬取,對這顆樹的遍歷就尤為重要了,這裡說到的深度優先、廣度優先為最常用的遍歷演算法。

邊敲邊學邊做,堅持學習分享。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31556503/viewspace-2216249/,如需轉載,請註明出處,否則將追究法律責任。

相關文章