目录
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;
}