木の幅優先探索(パート1):対人関係の6度理論は正しいですか?

木の幅優先探索(パート1):対人関係の6度理論は正しいですか?

ソーシャルネットワークの友達

LinkedIn、Facebook、WeChat、QQなどのソーシャルネットワーキングプラットフォームには多数のユーザーがいます。これらのソーシャルネットワークで非常に重要な部分は、人々の「友達」関係です。

数学では、この種の友人関係を表現するために、通常、グラフのノードを使用して人を表し、グラフのエッジを使用して人の間の知り合いを表します。ソーシャルネットワークでは、グラフ理論を使用して言った。「知人関係」は、一方向性と双方向性に分けられます。

一方向表現、2人のaとb、aはbを知っていますが、bはaを知りません。一方向の関係の場合、有向エッジを使用して、aがbを知っているか、bがaを知っているかを区別する必要があります。双方向の関係である場合、2つの側はお互いを認識しているため、無向エッジを直接使用するだけで十分です。

img

上記の例からわかるように、人々の間の知人関係への複数のパスが存在する可能性があります。たとえば、Zhang SanはZhao Liuに直接接続したり、Wang Wuを介してZhao Liuに接続したりできます。2つのパスを比較すると、最短パスの長さは1なので、Zhang SanとZhao Liuはかつて友達でした。つまり、ここでは、2つの間の最短経路の長さを使用して、彼らが何回友人であるかを定義します。この定義によれば、以前の社会関係図では、張山、王呉、趙劉は1度の友達で、李Siと趙劉と王呉は2度の友達でした。

img

ユーザーを指定すると、彼の2度の友達を最初に見つける方法は?

深さ優先検索で直面する問題

深度最適化検索を使用する場合、ループを生成するエッジに遭遇したら、フィルターをかける必要があります。具体的な操作は、新しいアクセスポイントが現在のチャネルに既に表示されているかどうかを判断することであり、発生した場合、再度アクセスされることはありません。

シックスディグリー理論は、あなたの社会的関係は、関係の程度が増すにつれて指数関数的に拡大することを教えてくれます。これは、ディープサーチ中に、ある程度の関係を追加するたびに、多数の友達が追加されることを意味します。

幅優先検索とは何ですか?

BFSとも呼ば(幅優先探索)、幅優先探索は、グラフ、エッジに沿って歩くとの結合点からノードを意味し、この時点1までの距離を見つけるために、他のすべてのポイント。始点からの距離が1の点をすべて検索した場合のみ、始点からの距離が2の点を検索します。始点から2の距離にあるすべての点が検索されると、始点から3の距離にある点が検索されます。

img

幅優先検索は、実際にはツリーを水平方向に検索することです。
幅優先検索と深さ優先検索の順序は異なりますが、2つの共通点もあります。
まず、進行中のプロセスでは、繰り返されるノードとエッジを取得したくないので、訪問されたポイントにマークを付け、その後の進行プロセスでは、マークされていないポイントのみにアクセスします。 。この点で、幅優先と深さ優先は一貫しています。違いは、幅優先では、特定のノードに直接接続されているポイントにアクセスしたことがわかった場合、次のステップは、このポイントの兄弟ノードに直接接続されているポイントを確認することです。訪問する新しいポイントがあります。

上の図では、ノード945の2つの子ノード580と762にアクセスした後、幅優先戦略は945に他の子ノードがないことを発見したので、945の兄弟ノード131をチェックして、どの子ノードを確認しますポイントはアクセス可能であるため、次に訪れるポイントは906です。深度優先では、特定のポイントに到達し、このポイントに直接接続されているすべてのポイントにアクセスしたことがわかった場合、その兄弟ノードは表示されませんが、このポイントの親ノードにフォールバックして続行します親ノードに直接接続されているポイントの中に新しいポイントがあるかどうかを確認します。たとえば、上の図では、ノード945の2つの子ノードにアクセスした後、深さ優先戦略はポイント110にフォールバックし、110の子ノード131にアクセスします。
第2に、幅優先検索では、始点に接続されているすべてのポイントにアクセスできるため、幅優先トラバーサルとも呼ばれます。グラフに接続されていない複数のサブグラフが含まれている場合、開始点からの幅優先検索では、サブグラフの1つしかカバーできません。現時点では、訪問されていない開始点を変更し、幅優先で別のサブグラフをトラバースし続ける必要があります。幅優先検索では、同じ方法を使用して、複数のサブグラフが接続されたグラフをトラバースできます。

ソーシャルフレンドのおすすめを実装する方法は?

見つかったすべてのノードを記録するときに、距離の短いポイントを優先的に訪問する方法は?よく見ると、始点に近いノードが先に発見されていることがわかります。つまり、ノードにアクセスするのが早ければ早いほど、ノードが処理されるのが早くなります。

ここでは、キューの先入れ先出し(先入れ先出し)データ構造を使用する必要があります。

それでは、幅優先検索でキューはどのように機能しますか?これは主に次のステップに分かれています。
まず、最初のノードをキューに入れます。その後、キューの先頭からノードが取得されるたびに、そのノードの下にあるすべてのノードが検索されます。次に、新しく検出されたノードをキューの最後に追加します。新しいノードが見つからなくなるまで上記の手順を繰り返します。

img

最初のステップでは、最初のノード110がキューに追加されます。
第2ステップでは、ノード110を取り出し、次のレベルのノード123、879、945、131を検索する。
手順3.キューの最後にポイント123、879、945、131を追加します。
ステップ4で、ステップ2と3を繰り返してノード123を処理し、新しく発見されたノード162と587をキューの最後に追加します。
ステップ5、ステップ2と3を繰り返し、ノード879を処理します。新しいノードは見つかりません。
ステップ6、ステップ2と3を繰り返してノード945を処理し、新しく発見されたノード580と762をキューの最後に追加します。
...
ステップn-1、ステップ2および3を繰り返し、ノード906を処理します。新しいノードは見つかりません。
ステップnで、ステップ2と3を繰り返してノード681を処理します。新しいノードは見つかりません。処理するノードがなくなり、プロセス全体が終了します。

  • ユーザーノードノード今回設計したユーザーノードは、ユーザーID user_idとユーザーのフレンドコレクションを含むプレフィックスツリーノードTreeNodeとは少し異なります。HashSetを使用して、ユーザー関係グラフを生成するときに重複する友達が存在するかどうかをユーザーが確認できるようにします。
  • グラフ全体のノード配列Node []を表します各ユーザーはuser_idで表されるため、連続配列を使用してすべてのユーザーを表すことができます。ユーザーのuser_idは、配列のインデックスです。
  • キューQueueはJavaのインターフェースなので、具体的な実装ではLinkedListクラスを使用する必要があります。

まとめ

ツリーまたはグラフをトラバースするときに、深さ優先方式を使用すると、検出されるノードの数が指数関数的に増加する場合があります。社会的関係の2度の友人など、最も近い接続ポイントに関心がある場合は、この場合、幅優先戦略の方が効率的です。幅優先を実現するために再帰的プログラミングやスタックデータ構造を使用できなくなったのは、まさにこの機能のためですが、先入れ先出しの特性を持つキューを使用する必要があります。

img

おすすめ

転載: www.cnblogs.com/liugangjiayou/p/12712077.html