圖也是一種 非線性結構,是由多個頂點組成的關係集合組成的一種數據結構。圖能夠分爲兩種,無向圖和有向圖。數組
★圖的定義:數據結構
★典型問題: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
★具體代碼: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(); }