并查集

什么是并查集?

并查集是一種樹型的數(shù)據(jù)結(jié)構(gòu),常用于處理一些不相交集合(Disjoint Sets)的合并及查詢問題。

并查集可以高效的進行如下操作:

  • 合并兩個不相同的集合
  • 判斷兩個元素是否屬于同一個集合

并查集常見操作

init()初始化所有元素獨立為一個集合(即父節(jié)點是自身)

  • 定義數(shù)組fa[],fa[x]存儲x的父節(jié)點。
  • 初始化所有元素的父節(jié)點為-1,若fa[x]=-1則代表元素x自身為一個集合。
void init(){
    memset(fa,-1,sizeof(fa));//
}

find()查找元素所在的集合返回根節(jié)點

  • 如果x獨立為一個集合,返回x,否則返回fa[x]。
int find(int x){
    if(fa[x]==-1) return x;
    return find(fa[x]);
}

unite(x,y)合并兩個不相同的集合

  • 先找到x和y的代表元素。
  • 如果相同,則說明x和y已經(jīng)屬于同一個集合,不用處理。
  • 如果不同,將一個代表元素指向另一個代表元素。
void unite(int x,int y){
    x=find(x);
    y=find(y);
    if(x==y) return;
    fa[x]=y;
}

same(x,y)判斷兩個元素是否屬于同一個集合

  • 分別找到x和y的代表元素。
  • 如果相同,說明x和y屬于同一個集合。
bool same(int x,int y){
    return find(x)==find(y);
}

并查集的優(yōu)化

路徑壓縮

尋找父節(jié)點是采用遞歸的方法,不采取任何判斷的合并,樹有可能會退化成一條鏈,每次find都會是O(n)的復(fù)雜度。所以必須進行路徑壓縮。在我們找到根節(jié)點的時候,直接把根節(jié)點作為它的父節(jié)點。

int find(int x){
    if(fa[x]==-1) return x;
    return fa[x=]find(fa[x]);
}

按樹的高度合并

合并時將元素所在深度低的集合合并到元素所在深度高的集合。

  • 定義一個deep[]數(shù)組,默認只有一個節(jié)點的集合深度為0;
  • 在unite()操作中,判斷x和y的高度,將高度小的樹連接到另一顆樹的根節(jié)點上。

void unite(int x,int y){
    
    x=find(x);
    y=find(y);
    if(x==y) return;
    if(deep[x]<deep[y]) fa[x]=y;
    else{
        fa[y]=x;
        if(deep[x]==deep[y]) deep[x]++;
    }
}

優(yōu)化后的代碼

int fa[N],deep[N];
void init(){
    memset(fa,-1,sizeof(fa));
    memset(deep,0,sizeof(deep));
}
int find(int x){
    if(fa[x]==-1) return x;
    return fa[x=]find(fa[x]);
}
void unite(int x,int y){
    
    x=find(x);
    y=find(y);
    if(x==y) return;
    if(deep[x]<deep[y]) fa[x]=y;
    else{
        fa[y]=x;
        if(deep[x]==deep[y]) deep[x]++;
    }
}
bool same(int x,int y){
    return find(x)==find(y);
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 并查集:使用集合中某個元素來代表這個集合,這個集合組織成樹狀結(jié)構(gòu),所有元素指向根節(jié)點。 (1)維護一個數(shù)組,用于存...
    伊凡的一天閱讀 271評論 0 1
  • 某次參加筆試的最后一題大意如下:給定一組用戶[0..n],以及他們之間的好友關(guān)系,問這些好友構(gòu)成了多少個朋友圈?例...
    Realizability閱讀 1,706評論 0 0
  • [本文新址: http://www.ahathinking.com/archives/10.html ] 并查集:...
    lintong閱讀 597評論 0 1
  • 1.問題描述: 有N個對象,對象間可以連通。假設(shè)有一個命令用來連接兩個對象,將兩個對象傳入該命令就會連接兩者,還有...
    luckygong閱讀 1,139評論 0 0
  • 今年第一次聞到桂花香是在校園里的一個晚上,那天已近深夜,我獨自一人從學生活動中心回金翰林休息。走過校醫(yī)院前...
    小楊林閱讀 449評論 0 0

友情鏈接更多精彩內(nèi)容