数据结构与算法——并查集数组实现
并查集
在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。
并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。
主要涉及操作: 初始化 把每个点所在集合初始化为其自身。 通常来说,这个步骤在每次使用该数据结构时只需要执行一次,无论何种实现方式,时间复杂度均为O(N)。 查找 查找元素所在的集合,即根节点。 合并 将两个元素所在的集合合并为一个集合。 通常来说,合并之前,应先判断两个元素是否属于同一集合,这可用上面的“查找”操作实现。
数组实现模板
下面用C++利用数组进行并查集实现:
//UnionFind.h
#pragma once
#define parent_max 1024
using namespace std;
struct Element
{
int val;
Element() {
}
Element(int va) :val(va) {
}
};
class UnionFind
{
public:
UnionFind();
UnionFind(int arr[], int len);
//UnionFind(int arr[], int len,int w);
~UnionFind();
int findHead(int element);
void unionSet(int element1, int element2);
bool isSameset(int element1, int element2);
private:
int parent[parent_max]; //用于存放第i个元素的父节点
};
//UnionFind.cpp
#include <iostream>
#include <string>
#include <unordered_map>
#include <map>
#include "UnionFind.h"
using namespace std;
UnionFind::UnionFind(){
}
UnionFind::~UnionFind(){
}
UnionFind::UnionFind(int arr[], int len)
{
//将数组中每个元素均加入并查集,自己是自己的父,也就是自己成集合
for (int i = 0; i < len; i++)
{
parent[arr[i]] = arr[i];
}
}
int UnionFind::findHead(int element)
{
int son = element;
int temp = 0;
//当element不等于他的parent,继续往找,直到他的parent
while (element != parent[element])
{
element = parent[element];
}
//优化:扁平化,沿途所有的element全部直接指向他的parent
while (son != element)
{
temp = parent[son];
parent[son] = element;
son = temp;
}
return element;
}
void UnionFind::unionSet(int element1, int element2)
{
//分别找到头,头相同不操作,头不同合并集合
int e1 = findHead(element1);
int e2 = findHead(element2);
if (e1 == e2)
return;
else
parent[e1] = parent[e2];
}
bool UnionFind::isSameset(int element1, int element2)
{
//头相同,则一定在同一个集合
return (findHead(element1) == findHead(element2));
}
