并查集

目录

 

First  定义

一、连接问题

二、路径问题

Second  效率慢

Union Find

Ex1:

Ex2:

Third  并查集的主流

Quick Union


First  定义

一、连接问题

 网络中节点间的连接状态
    1.网络是个抽象概念:用户之间形成的网络
    2.数据库中的音乐,电影,书记

数学中的集合类实现

二、路径问题

连接问题比路径问题要回答的问题少
    和二分查找作比较
    和select作比较 排名第n第元素
    和堆作比较 将数据中把最大值和最小值给找出来


算法设计思路:
    你设计第算法除了回答问题本身,是否额外回答了别的问题,如果额外回答了问题,就可能有更高效第算法


Second  效率慢

Union Find

    1.union( p , q )将两个元素连接
    2.find( p )查找p这个元素具体在哪个组
    3.isConnected( p , q )

    每一个同样的组都有同一个id号


Ex1:

       0 1 2 3 4 5 6 7 8 9
----------------------------------
id    0 0 0 0 0 1 1 1 1 1

    表示 0-4是相连的 5-9是相连的

Ex2:

       0 1 2 3 4 5 6 7 8 9
-----------------------------------
id    0 1 0 1 0 1 0 1 0 1

    表示 0 2 4 6 8是相连的 1 3 5 7 9是相连的

#include<iostream>
using namespace std;

class UnionFind{

private:
	int* id;
	int count;

public:
	UnionFind( int n ){
		count = n;
		id = new int[n];
		for( int i = 0 ; i < n ; i++)
			id[i] = i;
	}
	~UnionFind(){
		delete [] id;
	}
	int find( int p ){
		assert( p >= 0 && p < count);
		return id[p];
	}
	bool isConnected( int p, int q){
		return find(p) == find(q);
	}
	void unionElements( int p, int q ){
		int pID = find(p);
		int qID = find(q);

		if(pID == qID) 
			return;
		
		for( int i = 0 ; i < count ; i ++ ){
			if( id[i] == pID )//保证两个组的id是一样的
				id[i] = qID;
		}
	}

};

int mian(){

	return 0;
}

Third  并查集的主流

Quick Union

将每一个元素看做是一个节点
     5-------2
     / \        / \
     6       7   3   1
    让每一个节点拥有一个父亲的指针就好

Ex:
0 1 2    5  7     8
                       | \
            6        3  9
                       |
                      4

             0 1 2 3 4 5 6 7 8 9
---------------------------------------------
parent  0 1 2 8 3 1 5 7 8 8

并查集中的3要和8连接时(8是parent),整个并查集都是要动地。其他的情况,只需要把q和p所在的并查集的根节点连接即可。

比如图中的9要和4连接,只需要把9的parent设置为8即可(其实9直接连接4也是可以地,不过这样会造成并查集的长度过长,后面再连接的时候遍历并查集时间会很长)


#include<iostream>
using namespace std;

class UnionFind{

private:
	int* parent;
	int count;

public:
	UnionFind( int count ){
		parent = new int[count];
		this->count = count;
		for( int i = 0 ; i < count ; i++)
			parent[i] = i;
	}
	~UnionFind(){
		delete [] parent;
	}
	int find( int p ){
		assert( p >= 0 && p < count);
		while( p != parent[p])
			p = parent[p];
		return p;
	}
	bool isConnected( int p, int q){
		return find(p) == find(q);
	}
	void unionElements( int p, int q ){
		int pRoot = find(p);
		int qRoot = find(q);

		if(pRoot == qRoot) 
			return;
		
		parent[pRoot] = qRoot;
	}

};

int mian(){

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值