| C++ 實習測試: 互斥集合 (disjoint-sets) 類別製作 |
| 時間: 60分鐘 (10:20 上傳時間截止) |
| 令集合 S 為整數 0 到 n-1 的集合,「互斥集合 (disjoint-sets)」資料結構 (或稱為「不相交集合」, 也稱為 union-find 資料結構, 或是 merge-find 資料結構) 的定義如下:
|
| 我們可以用 陣列 簡單地實作 「互斥集合」資料結構, 用樹狀架構來代表各個子集合, 例如 DS2 = {0, 1, 2, 5}, {3, 6, 7}, {4} 表示為下圖之三個樹狀架構
用樹根節點作為這個子集合的代表元素, 下圖的整數陣列中每一個元素 parent[i] 中紀錄的是節點 i 的父節點, 如果是根節點的話 parent[i] 記錄的是 i 自己, 例如 DS2 = {0, 1, 2, 5}, {3, 6, 7}, {4} 以下列整數陣列表示
注意: 用這種表示方法來表示子集合並不是唯一的,同一個子集合可以有不同的樹狀架構,不考慮效率的情況下這個實作可以滿足下列 main() 函式中的基本測試 |
#include <cstdlib>
#include <cassert>
#include <iostream>
#include <iomanip>
using namespace std;
void makeSets(int nNodes, int parent[]);
int findSets(int i, int nNodes, const int parent[]);
void mergeTrees(int i, int j, int nNodes, int parent[]);
void unionSets(int i, int j, int nNodes, int parent[]);
int equalSets(int nNodes1, const int parent1[], int nNodes2, const int parent2[]);
void printSets(int nNodes, const int parent[]);
int main()
{
const int nNodes=8;
int parent[nNodes];
int i;
const int p1[8] = {0,1,2,3,4,5,6,7};
const int p2[8] = {0,0,2,3,4,5,6,7};
const int p3[8] = {0,0,3,3,4,5,6,7};
const int p4[8] = {0,0,3,3,4,4,6,7};
const int p5[8] = {0,0,3,3,5,5,5,7};
const int p6[8] = {0,0,3,3,6,4,6,6};
const int p7[8] = {0,0,3,4,6,4,6,6};
const int p8[8] = {7,0,3,4,6,4,6,6};
makeSets(nNodes, parent);
assert(equalSets(nNodes, parent, nNodes, p1));
unionSets(0, 1, nNodes, parent);
assert(equalSets(nNodes, parent, nNodes, p2));
unionSets(2, 3, nNodes, parent);
assert(equalSets(nNodes, parent, nNodes, p3));
unionSets(4, 5, nNodes, parent);
assert(equalSets(nNodes, parent, nNodes, p4));
unionSets(4, 6, nNodes, parent);
assert(equalSets(nNodes, parent, nNodes, p5));
unionSets(4, 7, nNodes, parent);
assert(equalSets(nNodes, parent, nNodes, p6));
unionSets(3, 7, nNodes, parent);
assert(equalSets(nNodes, parent, nNodes, p7));
unionSets(2, 1, nNodes, parent);
assert(equalSets(nNodes, parent, nNodes, p8));
printSets(nNodes, parent);
system("pause");
return 0;
}
void printSets(int nNodes, const int parent[])
{
int i, j;
int *printed = (int *) malloc(nNodes*sizeof(int));
for (i=0; i<nNodes; i++) printed[i] = 0;
for (i=0; i<nNodes; i++)
if (!printed[i])
{
if (i==0)
cout << "{";
else
cout << ", {";
cout << i;
for (j=i+1; j<nNodes; j++)
if (!printed[j] &&
findSets(i, nNodes, parent)==findSets(j, nNodes, parent))
{
cout << ", " << j;
printed[j] = 1;
}
cout << "}";
}
cout << endl;
free(printed);
}
void makeSets(int nNodes, int parent[])
{
int i;
for (i=0; i<nNodes; i++)
parent[i] = i;
}
int findSets(int i, int nNodes, const int parent[])
{
if ((i<0)||(i>=nNodes)) return -1;
if (i == parent[i]) return i;
return findSets(parent[i], nNodes, parent);
}
void mergeTrees(int i, int j, int nNodes, int parent[])
{
if ((i<0)||(i>=nNodes)) return;
if ((j<0)||(j>=nNodes)) return;
parent[i] = j;
}
void unionSets(int i, int j, int nNodes, int parent[])
{
if ((i<0)||(i>=nNodes)) return;
if ((j<0)||(j>=nNodes)) return;
mergeTrees(findSets(i, nNodes, parent),
findSets(j, nNodes, parent),
nNodes, parent);
}
int equalSets(int nNodes1, const int parent1[], int nNodes2, const int parent2[])
{
// 請實作一個測試兩個 disjoint-sets 是否相等的函式, 相等請回傳 1, 不等請回傳 0
// 首先檢查兩個 disjoint-sets 的元素個數是否相等
// 測試兩個集合 S1 與 S2 是否相等的基本方法是檢查 S1 中的每一個元素是否在 S2 裡,
// 同時反過來檢查 S2 中的每一個元素是否在 S1 裡, 請運用 findSet() 函式來測試,
// 請考慮兩個集合的代表元素可能會不一樣
return 1;
}
|
考試時間: 60分鐘 (10:20 上傳時間截止)
|
| 將所完成的 project (只需保留 .cpp, .h, .sln 以及 .vcxproj 檔案即可; 刪除掉 .suo, .sdf, .filters, .users, debug\ 資料匣, 以及 ipch\ 資料匣下的所有內容) 以 zip/rar/7zip 程式將整個資料匣壓縮起來, 在「考試作業」繳交區選擇 Labtest1上傳 |
後續練習這個 DisjointSets 物件可以用來
演算法大致描述如下: Initialize DisjointSets S with n=nRows*nCols elements and an nRows x nCols maze of '*' except maze[0][0] andthe following 4 cases do not satisfy the "route constraints" |

|
回
C++ 物件導向程式設計課程
首頁
製作日期: 03/21/2016 by 丁培毅 (Pei-yih Ting) E-mail: pyting@mail.ntou.edu.tw TEL: 02 24622192x6615 海洋大學 電機資訊學院 資訊工程學系 Lagoon |