幅優先探索アルゴリズムBFSの説明とPythonの実装

1.写真紹介

サンフランシスコに住んでいて、ツインピークスからゴールデンゲートブリッジに行き、バスで行きたいとします。

転送が最も少ないルートを見つけるために、どのようなアルゴリズムを使用しますか?

ゴールデンゲートブリッジは突き出ていないので、一気にそこにたどり着くのは不可能です。それは2つのステップで行うことができますか?

ゴールデンゲートブリッジは突き出ておらず、2段で行くことはできません。3つのステップができますか?

ゴールデンゲートブリッジが目立ちます!ツインピークスから出発して、次のルートに沿って3つのステップでゴールデンゲートブリッジに到達できます。

ゴールデンゲートブリッジへのルートは他にもありますが、もっと遠いです(4つのステップが必要です)。このアルゴリズムにより、ゴールデンゲートブリッジへの最短経路には3つのステップが必要であることがわかりました。この問題は、最短経路問題と呼ばれます。
最短経路を解くためのアルゴリズムは、幅優先探索と呼ばれます。
2つのステップが必要です:

  1. ダイアグラムを使用して問題をモデル化します。
  2. 幅優先探索を使用して問題を解決します。

図1図
は、一連の接続をシミュレートします。あなたとあなたの友人がトランプをしていて、誰が誰に借りているかをシミュレートするとします。

アレックスはラマのお金を借りており、トムはアディットのお金を借りています。グラフはノードとエッジで構成されています。

グラフはノードとエッジで構成されています。1つのノードは、多くのノードで直接接続できます。これらのノードはネイバーと呼ばれます。前の未払い金の図では、ラーマはアレックスの隣人であり、アディットは直接接続されていないためアレックスの隣人ではありませんが、アディットはラーマの隣人でありトムの隣人です。

2.幅優先探索

幅優先探索は通常、次の2種類の問題を解決するために使用されます。

  1. ポイントAから始めて、ノードBへのパスはありますか?
  2. ノードBへの最短経路であるポイントAから開始しますか?

数値例
この論文では、アルゴリズムを使用して問題1を解決します。

あなたがマンゴー農場を経営していて、これらのマンゴーを彼に売るためにマンゴー売り手を見つける必要があるとしましょう。このためにあなたはあなたの友人でそれを見つけることができます。

最初に友達のリストを作成し、次にリスト内の各人をチェックして、彼がマンゴーの売り手であるかどうかを確認します。

あなたの友人の誰もがマンゴーの売り手ではないと仮定して、あなたは友人の友人の中からそれを探す必要があります。

リストの全員をチェックするときは、友達をリストに追加します

このように、あなたは友達の間だけでなく、友達の友達の間でも検索しています。

上記は問題1を解決する方法を説明し、以下はアルゴリズムを介して問題2を解決する方法を説明します。
たとえば、最も近いマンゴーの売り手は誰ですか。たとえば、友人には1度の関係があり、友人の友人には2度の関係があります。

あなたの意見では、1度の関係は2度の関係よりも優れています。まず、1度の関係を探します。マンゴーの売り手がいない場合は、2度の関係を探します。
これは、幅優先探索の仕組みであり、最初に1次の関係をチェックし、次に2次の関係をチェックします。
この質問では、1次の関係が2次の関係の前にリストに追加されていることを理解できます。リストの各人をチェックして、彼がマンゴーの売り手であるかどうかを確認し、2度目の関係でそれを探します。

この質問では、知識ポイントを適用する必要があります。キュー
キューは、先入れ先出しの特性を持つデータ構造です。たとえば、バスに乗るために列に並ぶと、最初の列が最初にバスに乗ります。

3.コードの実装

1.図を使用して問題をモデル化します。
まず、コードを使用してグラフを実装する必要があります。グラフはノードと隣接ノードで構成されています。[I:Yu Dengwu]、[My Neighbors:Xiao Ming、XiaoBai]のマッピング関係を表現します。これにはハッシュテーブルが必要です。

ハッシュテーブルはキーを値にマップでき、ここでは、あなたを友達にマップできます。

Pythonでは、ハッシュテーブルを表すために辞書が使用されます。

graph={
    
    }
graph['you']=["alice","bob","claire"]


全体像

graph={
    
    }
graph['you']=["alice","bob","claire"]
graph['bob']=["anuj","peggy"]
graph['alice']=["peggy"]
graph['claire']=["thom","jonny"]
graph['anuj']=[]
graph['peggy']=[]
graph['thom']=[]
graph['jonny']=[]

2.幅優先探索を使用して、問題の
アルゴリズムフローを解決します

プロセスではキューが使用されます。キューは、先入れ先出し特性を備えたデータ構造です。たとえば、バスに乗るために列に並ぶと、最初の列が最初にバスに乗ります。Pythonはdequeを使用してキューを作成します。

コード

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: yudengwu(余登武)
# @Date  : 2021/1/04
#@email:[email protected]

#定义图
graph={
    
    }
graph['you']=["alice","bob","claire"]
graph['bob']=["anuj","peggy"]
graph['alice']=["peggy"]
graph['claire']=["thom","jonny"]
graph['anuj']=[]
graph['peggy']=[]
graph['thom']=[]
graph['jonny']=[]


#检查是否是芒果销售商。如果名字最后一个字母为m就是芒果销售商
def person_is_seller(name):
    return name[-1] =='m'


#

from collections import deque #导入队列
search_deque=deque()#创建一个队列
search_deque+=graph['you']
#print(search_deque) #deque(['alice', 'bob', 'claire'])

#检查部分代码
try:

    while search_deque:  # 只有队列不为空
        find = False  # 定义是否找到
        person = search_deque.popleft()  # 取出队列中的第一个人
        if person_is_seller(person):
            print(person + "是芒果销售商")
            find = True
            break

        else:
             search_deque += graph[person]  # 将朋友的朋友添加进队列
finally:
    if find==False:
        print('没有找到')

運転結果

このコードの終了条件:

  1. マンゴー商人を探す
  2. キューが空になります。つまり、友達のサークルにマンゴー商人がいません。

コード最適化
コード最適化
ペギー両方アリスの友達ボブは友達なので、彼女は2回キューに追加されます。1回はアリスの友達を追加するとき、もう1回はボブの友達が追加したときです。したがって、検索キューには2つのペギーがあります。
ペギーは1回しかチェックできません。人をチェックした後、その人をチェック済みとしてマークします。そして、彼を二度とチェックしないでください。これを行わないと、友達との関係が示されているとおりであれば、すぐに無限ループに陥る可能性があります。

最終コード

#定义图,图中每个人的朋友关系都要写
graph={
    
    }
graph['you']=["alice","bob","claire"]
graph['bob']=["anuj","peggy"]
graph['alice']=["peggy"]
graph['claire']=["thom","jonny"]
graph['anuj']=[]
graph['peggy']=[]
graph['thom']=[]
graph['jonny']=[]


#检查是否是芒果销售商。如果名字最后一个字母为m就是芒果销售商
def person_is_seller(name):
    return name[-1] =='m'


#检查是否是芒果商代码

from collections import deque #导入队列
search_deque=deque()#创建一个队列


def search(name):
    search_deque = deque()  # 创建一个队列
    search_deque += graph[name]#将一级关系添加进队列,即自己的朋友

    searched=[]#定义是否检查

    try:

        while search_deque:  # 只有队列不为空
            find = False  # 定义是否找到
            person = search_deque.popleft()  # 取出队列中的第一个人
            if person not in searched:#如果这个人没有被检查
                if person_is_seller(person):#如果这个人是芒果商
                    print(person + "是芒果销售商")
                    find = True
                    break
                else: #如果不是芒果商
                    search_deque += graph[person]  # 将朋友的朋友添加进队列
                    searched.append(person)#将这个人标记为已检查
    finally:
        if find == False:
            print('没有找到')

search('you')

運転結果


上記の最短経路を印刷してください。マンゴーサプライヤーのトムが見つかりました。今度は、トムの関係を印刷する必要があります。

私はここで、反転テーブルの知識を使用して達成します

仮説

元の辞書は
{'QuestionIID':[Keyword 1、Keyword 2 ...]、 'Question 2ID':[Keyword 2、Keyword 3 ...] ...}

処理された転置リストは、
{'Keyword 1':[Question 1ID]、 'Keyword 2':[Question 1ID、Question 2ID ...}です。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Author: yudengwu(余登武)
# @Date  : 2021/1/04
#@email:[email protected]

#定义图
graph={
    
    }
graph['you']=["alice","bob","claire"]
graph['bob']=["anuj","peggy"]
graph['alice']=["peggy"]
graph['claire']=["thom","jonny"]
graph['anuj']=[]
graph['peggy']=[]
graph['thom']=[]
graph['jonny']=[]



#所有问题组合起来的倒排表 result
result = {
    
    }
for i in graph.keys():
    left,rights=i,graph[i]
    for right in rights:
        if right in result.keys():
            result[right].append(left)
        else:
            result[right] = [left]
#print(result)
#得到的结果{'alice': ['you'], 'bob': ['you'], 'claire': ['you'], 'anuj': ['bob'], 'peggy': ['bob', 'alice'], 'thom': ['claire'], 'jonny': ['claire']}



def print_searchname(name1,name2):#name1为芒果商的名字即终点,name2为起点
    parent=result[name1] #终点的上一级.格式['claire']
    parent=''.join(parent)#去除中括号 得到格式 claire


    print('终点是{0}'.format(name1))
    while True:
        if parent !=name2:
            print("上一级是{0}".format(parent) )

            parent=result[parent]
            parent = ''.join(parent)
        if parent ==name2:
            print('{0}的上一级是终点{1}'.format(parent,name2))
            break
print_searchname('thom','you')

ここに画像の説明を挿入します
ここに画像の説明を挿入します

この記事には参考書「グラフィックアルゴリズム」があります
著者:Electrical-Yu Dengwu

おすすめ

転載: blog.csdn.net/kobeyu652453/article/details/112172645