并查集一般用于多元素,多集合的查找問題;
聽說很有用,但是平時(shí)好像確實(shí)沒有怎么見過。。
leetcode典型例題:島嶼數(shù)量
這里先定義一個(gè)節(jié)點(diǎn)結(jié)構(gòu):
templateclass EleNode
{public:
T value;
EleNode* father;
EleNode(T val)
{value = val;
father = nullptr;
}
};
主結(jié)構(gòu)中:
nodeMap
根據(jù)用戶數(shù)據(jù)存儲(chǔ)對(duì)應(yīng)節(jié)點(diǎn)數(shù)據(jù),所有被創(chuàng)建出來的節(jié)點(diǎn)都被存放在里面numMap
僅用于記錄該集合的元素?cái)?shù)量(只記錄頭部元素,因?yàn)檫@個(gè)數(shù)據(jù)只需要一條)void createNode(T val)
函數(shù)中,創(chuàng)建節(jié)點(diǎn)需要在nodeMap
和numMap
中初始化templateclass UnionFindSet
{//節(jié)點(diǎn)記錄
unordered_map*>nodeMap;
//元素集數(shù)量記錄
unordered_map*, int>numMap;
public:
UnionFindSet(){}
//構(gòu)造函數(shù)
UnionFindSet(const vector& list)
{for (int i = 0; i< list.size(); i++)
{ createNode(list[i]);
}
}
//銷毀節(jié)點(diǎn)
~UnionFindSet()
{for (auto ele : nodeMap)
{ delete ele.second;
}
}
// 新建一個(gè)節(jié)點(diǎn)
void createNode(T val)
{if (nodeMap.find(val) != nodeMap.end()) return;
EleNode* newNode = new EleNode(val);
nodeMap.insert(make_pair(val, newNode));
numMap.insert(make_pair(newNode, 1));
}
}
主要方法:有三個(gè)方法,分別為:
// 判斷是否在同個(gè)集合中
bool isSameSet(const T& v1, const T& v2);
// 執(zhí)行聯(lián)合,即合并節(jié)點(diǎn)
void doUnion(EleNode* t1, EleNode* t2);
//找頭節(jié)點(diǎn)
EleNode* findHead(EleNode* node);
// 是否為同個(gè)集合
bool isSameSet(const T& v1, const T& v2)
{assert(nodeMap.find(v1) != nodeMap.end() && nodeMap.find(v2) != nodeMap.end());
return findHead(nodeMap[v1]) == findHead(nodeMap[v2]);
}
1>首先判斷他們是否已經(jīng)在同個(gè)集合中,在同集合中就跳出。
2>再分別找到他們兩個(gè)的集合數(shù)量中的較大值和較小值
3>將數(shù)量較小的一方并入數(shù)量較大的一方,通過將較小集合頭節(jié)點(diǎn)的father
指向改為較大集合頭部
4>更新集合數(shù)量值
// 執(zhí)行聯(lián)合
void doUnion(EleNode* t1, EleNode* t2)
{// 判斷頭節(jié)點(diǎn)并保存
EleNode* head1 = findHead(t1);
EleNode* head2 = findHead(t2);
if (head1 == head2) return;
//找較大較小集合
EleNode* big = numMap[head1] >= numMap[head2] ? head1 : head2;
EleNode* small = numMap[head1] >= numMap[head2] ? head2 : head1;
//改頭
small->father = big;
//數(shù)值更新
numMap[big] = numMap[big] + numMap[small];
numMap.erase(small);
}
public:
// 執(zhí)行聯(lián)合外部接口
void doUnion(const T& v1, const T& v2)
{assert(nodeMap.find(v1) != nodeMap.end() && nodeMap.find(v2) != nodeMap.end());
doUnion(nodeMap[v1], nodeMap[v2]);
}
O(1)
例:從2位置開始,找到集合頭部
執(zhí)行后:
下面的函數(shù)中,將所有走過的路徑全部壓入棧內(nèi),并在找到頭節(jié)點(diǎn)后,挨個(gè)將他的父親改為頭節(jié)點(diǎn),最后返回頭部。
//找頭
EleNode* findHead(EleNode* node)
{stack*>path;
while (node->father != nullptr)
{ path.push(node);
node = node->father;
}
while (!path.empty())
{ path.top()->father = node;
path.pop();
}
return node;
}
二、全部代碼#include#include#include#include#includeusing namespace std;
templateclass EleNode
{public:
T value;
EleNode* father;
EleNode(T val)
{value = val;
father = nullptr;
}
};
templateclass UnionFindSet
{//節(jié)點(diǎn)記錄
unordered_map*>nodeMap;
//元素集數(shù)量記錄
unordered_map*, int>numMap;
//找頭
EleNode* findHead(EleNode* node)
{stack*>path;
while (node->father != nullptr)
{ path.push(node);
node = node->father;
}
while (!path.empty())
{ path.top()->father = node;
path.pop();
}
return node;
}
// 執(zhí)行聯(lián)合
void doUnion(EleNode* t1, EleNode* t2)
{EleNode* head1 = findHead(t1);
EleNode* head2 = findHead(t2);
if (head1 == head2) return;
//合并
EleNode* big = numMap[head1] >= numMap[head2] ? head1 : head2;
EleNode* small = numMap[head1] >= numMap[head2] ? head2 : head1;
small->father = big;
numMap[big] = numMap[big] + numMap[small];
numMap.erase(small);
}
public:
UnionFindSet(){}
//構(gòu)造函數(shù)
UnionFindSet(const vector& list)
{for (int i = 0; i< list.size(); i++)
{ createNode(list[i]);
}
}
//銷毀節(jié)點(diǎn)
~UnionFindSet()
{for (auto ele : nodeMap)
{ delete ele.second;
}
}
// 新建一個(gè)節(jié)點(diǎn)
void createNode(T val)
{if (nodeMap.find(val) != nodeMap.end()) return;
EleNode* newNode = new EleNode(val);
nodeMap.insert(make_pair(val, newNode));
numMap.insert(make_pair(newNode, 1));
}
// 判斷是否在同個(gè)集合中
bool isSameSet(const T& v1, const T& v2)
{assert(nodeMap.find(v1) != nodeMap.end() && nodeMap.find(v2) != nodeMap.end());
return findHead(nodeMap[v1]) == findHead(nodeMap[v2]);
}
// 執(zhí)行聯(lián)合外部接口
void doUnion(const T& v1, const T& v2)
{assert(nodeMap.find(v1) != nodeMap.end() && nodeMap.find(v2) != nodeMap.end());
doUnion(nodeMap[v1], nodeMap[v2]);
}
};
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧
新聞標(biāo)題:C++實(shí)現(xiàn)并查集結(jié)構(gòu)-創(chuàng)新互聯(lián)
文章URL:http://jinyejixie.com/article28/dcjicp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供全網(wǎng)營(yíng)銷推廣、外貿(mào)建站、網(wǎng)站設(shè)計(jì)公司、手機(jī)網(wǎng)站建設(shè)、品牌網(wǎng)站建設(shè)、域名注冊(cè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容