并查集

并查集

并查集是一種樹形的數(shù)據(jù)結構沛励,顧名思義,它用于處理一些不交集的 合并 及 查詢 問題钝侠。 它支持兩種操作:

  • 查找(Find):確定某個元素處于哪個子集疤坝;
  • 合并(Union):將兩個子集合并成一個集合。

并查集不支持集合的分離披摄,但是并查集在經(jīng)過修改后可以支持集合中單個元素的刪除操作(詳見 UVA11987 Almost Union-Find)亲雪。使用動態(tài)開點線段樹還可以實現(xiàn)可持久化并查集

查找

通俗地講一個故事:幾個家族進行宴會,但是家族普遍長壽疚膊,所以人數(shù)眾多义辕。由于長時間的分離以及年齡的增長,這些人逐漸忘掉了自己的親人寓盗,只記得自己的爸爸是誰了灌砖,而最長者(稱為「祖先」)的父親已經(jīng)去世,他只知道自己是祖先贞让。為了確定自己是哪個家族周崭,他們想出了一個辦法,只要問自己的爸爸是不是祖先喳张,一層一層的向上問续镇,直到問到祖先。如果要判斷兩人是否在同一家族销部,只要看兩人的祖先是不是同一人就可以了摸航。

在這樣的思想下,并查集的查找算法誕生了舅桩。

并查集.png
int fa[MAXN];  // 記錄某個人的爸爸是誰酱虎,特別規(guī)定,祖先的爸爸是他自己
int find(int x) {
  // 尋找x的祖先
  if (fa[x] == x)  // 如果x是祖先則返回
    return x;
  else
    return find(fa[x]);  // 如果不是則x的爸爸問x的爺爺
}

顯然這樣最終會返回x的祖先擂涛。

路徑壓縮

這樣的確可以達成目的读串,但是顯然效率實在太低。為什么呢撒妈?因為我們使用了太多沒用的信息恢暖,我的祖先是誰與我父親是誰沒什么關系,這樣一層一層找太浪費時間狰右,不如我直接當祖先的兒子杰捂,問一次就可以出結果了。甚至祖先是誰都無所謂棋蚌,只要這個人可以代表我們家族就能得到想要的效果嫁佳。把在路徑上的每個節(jié)點都直接連接到根上挨队,這就是路徑壓縮

并查集-路徑壓縮.png

這樣我們的代碼可以做這樣的修改

int fa[MAXN];  // 記錄某個人的爸爸是誰蒿往,特別規(guī)定盛垦,祖先的爸爸是他自己
int find(int x) {
  // 尋找x的祖先
  if (fa[x] == x)  // 如果x是祖先則返回
    return x;
  else
    return fa[x] = find(fa[x]); 
}
合并

宴會上,一個家族的祖先突然對另一個家族說:我們兩個家族交情這么好熄浓,不如合成一家好了情臭。另一個家族也欣然接受了。
我們之前說過赌蔑,并不在意祖先究竟是誰,所以只要其中一個祖先變成另一個祖先的兒子就可以了竟秫。

并查集-合并.png
void unionSet(int x, int y) {
    //我們將學x娃惯,y所在的家族進行合并
    //我們只需要找到他們的祖先find(x) = find(y)
    x = find(x)
    y = find(y)
    fa[x] = y
}
啟發(fā)式合并(按秩合并)

一個祖先突然抖了個機靈:「你們家族人比較少,搬家到我們家族里比較方便肥败,我們要是搬過去的話太費事了趾浅。」

由于需要我們支持的只有集合的合并馒稍、查詢操作皿哨,當我們需要將兩個集合合二為一時,無論將哪一個集合連接到另一個集合的下面纽谒,都能得到正確的結果证膨。但不同的連接方法存在時間復雜度的差異。具體來說鼓黔,如果我們將一棵點數(shù)與深度都較小的集合樹連接到一棵更大的集合樹下央勒,顯然相比于另一種連接方案,接下來執(zhí)行查找操作的用時更邪幕(也會帶來更優(yōu)的最壞時間復雜度)崔步。
當然,我們不總能遇到恰好如上所述的集合————點數(shù)與深度都更小缎谷。鑒于點數(shù)與深度這兩個特征都很容易維護井濒,我們常常從中擇一,作為估價函數(shù)列林。而無論選擇哪一個瑞你,時間復雜度都為 O(n),

如果只使用啟發(fā)式合并席纽,而不使用路徑壓縮捏悬,時間復雜度為O(mlog n) 。由于路徑壓縮單次合并可能造成大量修改润梯,有時路徑壓縮并不適合使用过牙。例如甥厦,在可持久化并查集、線段樹分治 + 并查集中寇钉,一般使用只啟發(fā)式合并的并查集刀疙。

std::vector<int> size(N, 1); // 記錄并初始化子樹的大小為 1
void unionSet(int x, int y) {
    int xx = find(x)
    int yy = find(y)
    if(xx == yy) return
    if (size[xx] > size[yy])  // 保證小的合到大的里
    swap(xx, yy);
    fa[xx] = yy;
    size[yy] += size[xx];
}
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市扫倡,隨后出現(xiàn)的幾起案子谦秧,更是在濱河造成了極大的恐慌,老刑警劉巖撵溃,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疚鲤,死亡現(xiàn)場離奇詭異,居然都是意外死亡缘挑,警方通過查閱死者的電腦和手機集歇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來语淘,“玉大人诲宇,你說我怎么就攤上這事』谭” “怎么了姑蓝?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吕粗。 經(jīng)常有香客問我纺荧,道長,這世上最難降的妖魔是什么溯泣? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任虐秋,我火速辦了婚禮,結果婚禮上垃沦,老公的妹妹穿的比我還像新娘客给。我一直安慰自己,他們只是感情好肢簿,可當我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布靶剑。 她就那樣靜靜地躺著,像睡著了一般池充。 火紅的嫁衣襯著肌膚如雪桩引。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天收夸,我揣著相機與錄音坑匠,去河邊找鬼。 笑死卧惜,一個胖子當著我的面吹牛厘灼,可吹牛的內(nèi)容都是我干的夹纫。 我是一名探鬼主播,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼设凹,長吁一口氣:“原來是場噩夢啊……” “哼舰讹!你這毒婦竟也來了?” 一聲冷哼從身側響起闪朱,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤月匣,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后奋姿,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锄开,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年称诗,在試婚紗的時候發(fā)現(xiàn)自己被綠了院刁。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡粪狼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出任岸,到底是詐尸還是另有隱情再榄,我是刑警寧澤,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布享潜,位于F島的核電站困鸥,受9級特大地震影響,放射性物質發(fā)生泄漏剑按。R本人自食惡果不足惜疾就,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望艺蝴。 院中可真熱鬧猬腰,春花似錦、人聲如沸猜敢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽缩擂。三九已至鼠冕,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間胯盯,已是汗流浹背懈费。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留博脑,地道東北人憎乙。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓票罐,卻偏偏與公主長得像,于是被迫代替她去往敵國和親寨闹。 傳聞我的和親對象是個殘疾皇子胶坠,可洞房花燭夜當晚...
    茶點故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容

  • 關于我的 Leetcode 題目解答,代碼前往 Github:https://github.com/chenxia...
    專職跑龍?zhí)?/span>閱讀 7,395評論 0 2
  • 并查集(Disjiont-set) [TOC] 更新5/23/2018 更新路徑壓縮代碼 簡介 wiki上關于并查...
    前幾閱讀 2,186評論 0 2
  • //本文首先發(fā)表于博客園繁堡,點擊這里查看我的博客沈善。廢話不多說,直接看題: 一看這道題椭蹄,我就有了思路:既然這道題身在圖...
    gzr666閱讀 418評論 0 1
  • 一闻牡、基本概念和定義 參考文章并查集(Union-find Sets)是一種非常精巧而實用的數(shù)據(jù)結構,它主要用于處理...
    一只可愛的檸檬樹閱讀 608評論 0 0
  • 并查集被很多OIer認為是最簡潔而優(yōu)雅的數(shù)據(jù)結構之一绳矩,主要用于解決一些元素分組的問題罩润。它管理一系列不相交的集合,并...
    Pecco閱讀 349評論 0 0