• 并查集--Disjoint Set


    算法并查集的学习

    用到的函数:

    • union_Vertices()//合并两个图的点集合
    • find_root()//找到一个集合的root

    用到的数据逻辑表示:

    • int parent[Vertices];//parent[x] = y表示序号为x的结点的父节点是序号为y的结点
    • int rank[Vertices];//用于压缩路径 优化算法 避免成串的情况出现
    • int edges[Vertices][2];//描述边的集合

    int find_root(int x, int parent[])函数的实现

    int find_root(int x, int parent[]) {
    	int x_root = x; //初始化为当前结点
    	while (parent[x_root] != -1) { //一直向上寻找知道找到root结点
    		x_root = parent[x_root];
    	}
    	return x_root;
    }
    

    int union_vertices(int x, int y, int parent[], int rank[])函数的实现

    int union_vertices(int x, int y, int parent[], int rank[]) {
    	int x_root = find_root(x, parent); // 找到x结点的root结点
    	int y_root = find_root(y, parent); // 找到y结点的root结点
    
    	if (x_root == y_root) return 0; // 两个若是同一root结点证明两个结点在同一集合内
    
    	//parent[x_root] = y_root;
            //开始优化路径
    	if (rank[x_root] > rank[y_root]) { //x的集合的层数大于y的集合的层数时 要把y的集合向x的集合合并 反之合并的集合的rank会增加1
    		parent[y_root] = x_root;
    	}
    	else if (rank[x_root] < rank[y_root]) {//y的集合的层数大于x的集合的层数时 要把x的集合向y的集合合并 反之合并的集合的rank会增加1
    		parent[x_root] = y_root;
    		}
    	else { //两个集合的层数相同时,可选任意的一个结点为另外一个结点的父结点, 并让父节点的rank增加1
    		parent[y_root] = x_root; //这里选择把x_root的结点当做y_root结点的父节点
    		rank[x_root] ++;//父节点x_root 的rank[x_root]++;
    	}
    
    	return 1;//返回1说明成功合并两个不同的集合
    }
    

    完整代码:

    
    #include <cstdio>
    #include <stdlib.h>
    
    
    
    #define VERTICES 6
    /*
     * Disjoint set 并查集
     * 难点在于实现union过程
    */
    
    void initialise(int parent[], int rank[]) {
    	int i;
    	for (i = 0; i < VERTICES; i++) {
    		parent[i] = -1;
    		rank[i] = 0;
    	}
    }
    int find_root(int x, int parent[]) {
    	int x_root = x;
    	while (parent[x_root] != -1) {
    		x_root = parent[x_root];
    	}
    	return x_root;
    }
    /* return 1 可以成功归并
    	return 0 不可以归并(已经在同一集合)
    */
    int union_vertices(int x, int y, int parent[], int rank[]) {
    	int x_root = find_root(x, parent);
    	int y_root = find_root(y, parent);
    
    	if (x_root == y_root) return 0;
    
    	//parent[x_root] = y_root;
    	if (rank[x_root] > rank[y_root]) {
    		parent[y_root] = x_root;
    	}
    	else if (rank[x_root] < rank[y_root]) {
    		parent[x_root] = y_root;
    		}
    	else {
    		parent[y_root] = x_root;
    		rank[x_root] ++;
    	}
    
    	return 1;
    }
    
    int main() {
    
    	int parent[VERTICES] = { 0 }; // 用于表示结点的父节点
    	int rank[VERTICES] = { 0 };
    	int edges[6][2] = { // 类似邻接矩阵
    		{0, 1}, {1, 2}, {1, 3},
    		{2, 4}, {3, 4}, {2, 5}
    	};
    
    	initialise(parent, rank);
    	for (int i = 0; i < 6; i++) {
    		int x = edges[i][0];
    		int y = edges[i][1];
    		if (union_vertices(x, y, parent, rank) == 0) {
    			printf("Cycle detected.
    ");
    			exit(0);
    		}
    	}
    	printf("No cycles found.
    ");
    
    	return 0;
    
    }
    
  • 相关阅读:
    C++经典书籍:游戏编程
    云计算学习笔记Hadoop简介,hadoop实现原理,NoSQL介绍...与传统关系型数据库对应关系,云计算面临的挑战
    A win for the Nokia N8 is a win for Qt
    Qt 为中国移动音乐客户端提供多平台支持
    诺基亚力邀App开发员加入Ovi以对抗苹果
    MeeGo手机或将跳票至2011年
    TinyXML:一个优秀的C++ XML解析器
    企业开发中Qt和.Net小谈
    Qt 的昨天,今天,明天
    学机械的看看吧,一般看不见的机械原理——全动画图解
  • 原文地址:https://www.cnblogs.com/DengSchoo/p/12643323.html
Copyright © 2020-2023  润新知