并查集优化

1 查询的优化——路径压缩

在查询函数find_set(int i)中,查询元素i所属的集,需要搜索路径找到根结点,返回的结果是根结点。这条搜索路径可能很长。如果在返回的时候,顺便把i所属的集改成根结点,那么下次再搜的时候,就能在O(1)的时间内得到结果。

/*---未优化---*/
int find_set(int x){               //查找
    return x==s[x]? x:find_set(s[x]);
}

/*---递归优化---*/
int find_set(int x){
    if(x != s[x]) 
       s[x] = find_set(s[x]);   //路径压缩
    return s[x];
}

/*---非递归优化---*/
int find_set(int x){
    int r = x;
    while ( s[r] != r ) r=s[r];  //找到根结点
    int i = x, j;
    while(i != r){         
         j = s[i];     //用临时变量j记录
         s[i]= r ;     //把路径上元素的集改为根结点
         i = j;
    }
    return r;
}

2 合并的优化

合并元素x和y时,先搜到它们的根结点,然后再合并这两个根结点,即把一个根结点的集改成另一个根结点。这两个根结点的高度不同,如果把高度较小的集合并到较大的集上,能减少树的高度。下面是优化后的代码,在初始化时用height[i]定义元素i的高度,在合并时更改。

int height[maxn];
void init_set(){						//初始化
   for(int i = 1; i <= maxn; i++){
        s[i] = i;
        height[i]=0;                     //树的高度
   }
}
void merge_set(int x, int y){         //优化合并操作
    x = find_set(x);
    y = find_set(y);
    if (height[x] == height[y]) {
        height[x] = height[x] + 1;      //合并,树的高度加一
        s[y] = x;       
    }
    else{                            //把矮树并到高树上,高树的高度保持不变
        if (height[x] < height[y])  s[x] = y;	// y<--x
        else   s[y] = x;					// x<--y
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值