数据结构实现 9.1:并查集_数组结构实现(C++版)

本文介绍了并查集这一高级数据结构,主要用于处理元素间的关系。使用数组实现并查集,通过元素的阶来表示所属集合。详细阐述了并查集的构造、联合操作、查找操作以及其他基本操作的程序实现,并分析了算法复杂度。最后提供了完整的C++代码实现。
摘要由CSDN通过智能技术生成

1. 概念及基本框架

并查集 是一种高级数据结构,主要用于表示元素间的关系,即元素是否归属于同一个集合。

并查集

如上图,不同的颜色表示不同的集合,里面的数字表示元素存储的数据。下面给出并查集的基本接口。

class UnionFind{
public:
	virtual int size() = 0;
	virtual bool isEmpty() = 0;
	//是否连接
	virtual bool isConnected(int p, int q) = 0;
	//联合元素
	virtual void unionElements(int p, int q) = 0;
};

我们使用数组来实现并查集,这里我们忽略每个元素的数据,用每个元素的阶表示元素本身,用数组中存的数字表示元素所属集合。那么并查集的实现过程如下:
1.将每个元素初始化成自身,在下面的构造函数中实现。
2.联合,将需要联合的元素中存储的数字统一为一个。
3.查找,只要数组中存储的数字是一样的,那么认为两个元素属于同一个集合。

class QuickFind : public UnionFind{
public:
	QuickFind(int size){
		m_data = new int[size];
		for (int i = 0; i < size; ++i){
			m_data[i] = i;
		}
		m_size = size;
	}
	...
private:
	int *m_data;
	int m_size;
};

m_data 用来表示数组。
m_size 表示并查集大小。
接下来我们就对并查集的联合、查询以及一些其他基本操作用代码去实现。

2. 基本操作程序实现

2.1 联合操作

class QuickFind : public UnionFind{
public:
	...
	//联合元素
	void unionElements(int p, int q){
		if (p == q){
			return;
		}
		for (int i = 0; i < m_size; ++i){
			if (m_data[i] == m_data[q]){
				m_data[i] = m_data[p];
			}
		}
	}
	...
};

联合元素时,需要遍历一遍数组,然后把需要联合的元素都联合起来。

2.2 查找操作

class QuickFind : public UnionFind{
public:
	...
	//是否连接
	bool isConnected(int p, int q){
		return find(p) == find(q);
	}
	...
private:
	int find(int index){
		if (index < 0 || index >= m_size){
			cout << "访问越界!" << endl;
			throw 0;
		}
		return m_data[index];
	}
	...
};

用于查找两个元素是否被联合在一起。

2.3 其他操作

线段树还有一些其他的操作,包括 并查集大小 等的查询操作。

class QuickFind : public UnionFind{
public:
	...
	int size(){
		return m_size;
	}
	bool isEmpty(){
		return m_size == 0;
	}
	void print(){
		cout << "QuickFind: " << "Size = " << m_size << endl;
		cout << '[';
		for (int i = 0; i < m_size; ++i){
			cout << m_data[i];
			if (i != m_size - 1){
				cout << ',';
			}
		}
		cout << ']' << endl;
	}
	...
};

3. 算法复杂度分析

3.1 联合操作

函数最坏复杂度平均复杂度
unionElementsO(n)O(n/2) = O(n)

因为要遍历一次数组,所以联合操作的时间复杂度为 O(n)

3.2 查找操作

函数最坏复杂度平均复杂度
isConnectedO(1)O(1)

总体情况:

操作时间复杂度
O(n)
O(1)

4. 完整代码

程序完整代码(这里使用了头文件的形式来实现类)如下:
虚函数接口 代码如下:

#ifndef __UNIONFIND_H__
#define __UNIONFIND_H__

class UnionFind{
public:
	virtual int size() = 0;
	virtual bool isEmpty() = 0;
	//是否连接
	virtual bool isConnected(int p, int q) = 0;
	//联合元素
	virtual void unionElements(int p, int q) = 0;
};

#endif

并查集 类代码:

#ifndef __QUICKFIND_H__
#define __QUICKFIND_H__

#include "UnionFind.h"

class QuickFind : public UnionFind{
public:
	QuickFind(int size){
		m_data = new int[size];
		for (int i = 0; i < size; ++i){
			m_data[i] = i;
		}
		m_size = size;
	}
	int size(){
		return m_size;
	}
	bool isEmpty(){
		return m_size == 0;
	}
	void print(){
		cout << "QuickFind: " << "Size = " << m_size << endl;
		cout << '[';
		for (int i = 0; i < m_size; ++i){
			cout << m_data[i];
			if (i != m_size - 1){
				cout << ',';
			}
		}
		cout << ']' << endl;
	}
	//是否连接
	bool isConnected(int p, int q){
		return find(p) == find(q);
	}
	//联合元素
	void unionElements(int p, int q){
		if (p == q){
			return;
		}
		for (int i = 0; i < m_size; ++i){
			if (m_data[i] == m_data[q]){
				m_data[i] = m_data[p];
			}
		}
	}
private:
	int find(int index){
		if (index < 0 || index >= m_size){
			cout << "访问越界!" << endl;
			throw 0;
		}
		return m_data[index];
	}
private:
	int *m_data;
	int m_size;
};

#endif
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
内含资源如下: 1.基本数据结构 1.1.Array ........... 动态数组 1.2.LinkedList ... 链表 1.3.BST .............. 二分搜索树 1.4.MapBST ..... 二分搜索树(用于实现映射) 1.5.AVLTree ...... AVL树 2.接口 2.1.Queue ........... 队列接口 2.2.Stack .............. 栈接口 2.3.Set .................. 集合接口 2.4.Map ............... 映射接口 2.5.Merger .......... 自定义函数接口 2.6.UnionFind ..... 并查集接口 3.高级数据结构 3.1.ArrayQueue .......................... 队列_基于动态数组实现 3.2.LinkedListQueue .................. 队列__基于链表实现 3.3.LoopQueue ........................... 循环队列_基于动态数组实现 3.4.PriorityQueue ....................... 优先队列_基于最大二叉堆实现 3.5.ArrayPriorityQueue ............. 优先队列_基于动态数组实现 3.6.LinkedListPriorityQueue ..... 优先队列_基于链表实现 3.7.ArrayStack ............................. 栈_基于动态数组实现 3.8.LinkedListStack ..................... 栈_基于链表实现 3.9.BSTSet ..................................... 集合_基于二分搜索树实现 3.10.LinkedListSet ....................... 集合_基于链表实现 3.11.BSTMap ................................ 映射_基于二分搜索树实现 3.12.AVLTreeMap ....................... 映射_ 基于AVL树实现 3.13.LinkedListMap .................... 映射_基于链表实现 3.14.MaxHeap ............................. 最大二叉堆 3.15.SegmentTree ...................... 线段树 3.16.Trie ......................................... 字典树 3.17.QuickFind ............................ 并查集_基于数组实现 3.18.QuickUnion ......................... 并查集_基于树思想实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值