圖—並查集(解決朋友圈問題)

      圖也是一種 非線性結構,是由多個頂點組成的關係集合組成的一種數據結構。圖能夠分爲兩種,無向圖和有向圖。數組


★圖的定義:數據結構

wKioL1eUFjzTw922AABLk_4oE4g613.png


★典型問題:ide

      利用圖可以解決不少問題,這裏有一個較爲典型的問題,假如已知有n我的和m對好友關係(存於數字r)。若是兩我的是直接或者間接的好友(即就是好友的好友...),則認爲他們屬於一個朋友圈,請寫出程序求出這n我的裏一共有多少個朋友圈。函數

      例如:n = 5, m = 3, r = {{1,2},{2,3},{4,5}}, 表示有5我的,1和2是朋友,2和3也是朋友,4和5是朋友,則1,2,3屬於一個朋友圈,四、5屬於另外一個朋友圈,結果爲2個朋友圈。spa



★解題思路:指針

      首先,先介紹一個概念:並查集。並查集就是將N個不一樣元素分紅一組不想交的集合,開始時,每一個元素就是一個集合,而後按規律將兩個集合進行合併。具體的作法以下:    blog

     設定一個有N個元素的數組,將每一個元素對應的位置都置爲-1,即就是先讓其沒有相交,而後根據題目中給出的朋友關係,將根節點元素對應的位置減1,將與根節點是好友的元素對應的位置更改成根節點元素,按照這樣的方式,將全部的關係都進行對應,最後數組中若是是負數,所對應的元素就是根節點。get


wKiom1eUHxySzhg_AAAl9PnIqoE328.png


★具體代碼:it

#pragma once
#include <assert.h>
//實現圖  ——並查集
/*
主要功能:給定一個範圍,可以肯定朋友圈的個數
*/

class UnionFindSet
{
public:
     UnionFindSet(size_t size)    //構造函數
          :_n(size)
          , _set(new int[size])
     {
          for (int i = 0; i < size; i++)     //將_set中的數據最早初始化爲-1
          {
               _set[i] = -1;
          }
     }
     
     void Union(int root1, int root2)    //結合兩個根節點
     {
          assert(_set[root1] < 0);
          assert(_set[root2] < 0);
          _set[root1] += _set[root2];
          _set[root2] = root1;
     }
     
     size_t FindRoot(int child)
     {
          if (_set[child] < 0)   //負數證實這個節點就是根節點
          {
               return child;
          }
          int num = _set[child];
          while (num >= 0)
          {
               num = _set[num];
          }
          return num;
     }
     
     void print()
     {
          int root = 0;
          for (int i = 0; i < _n; i++)
          {
               if (_set[i] < 0)
               {
                    root++;
               }
          }
          cout << "輸出有幾個朋友圈:" << root << endl;
     }
     
protected:
     int* _set;    //數組指針
     size_t _n;     //給定範圍數據的個數
};

void Test()
{
 UnionFindSet ht(10);
 ht.Union(0, 6);
 ht.Union(0, 7);
 ht.Union(0, 8);
 ht.Union(1, 4);
 ht.Union(1, 9);
 ht.Union(2, 3);
 ht.Union(2, 5);
 ht.print();
}
相關文章
相關標籤/搜索