您的位置:首页 > 理论基础 > 数据结构算法

数据结构 练习 22-并查集以及图的最小生成树

2013-07-12 19:19 246 查看

前言

本博客主要介绍并查集以及图的最小生成树。对于并查集,我们引入其基本概念,并分析其复杂度,最后利用并查集来分析最小生成树。

并查集

参考文献《算法导论》,博客 /article/2388807.html
并查集包括三个操作:make_set,find_set,union_set。

链表表示:



每个节点包括一个value,两个指针:一个指向下一个节点,一个指向头节点,还包括一个head和一个tail;
每一个集合的代表为头结点,所以每个节点都得指向头结点,这样能迅速定位头结点。
复杂度如下



树根表示:

树根表示,可以引入两种优化,按秩合并,路径压缩,当同时使用这优化时,最坏情况运行时间为:O(m*α(n)),m是总的操作次数,α(n)是一个增长及其缓慢的函数,通常[b]α(n)<=4;所以最坏情况的复杂度可以看做是线性的;[/b]

图的最小生成树

图作为一种复杂的数据结构,前面 简单学习了图的遍历,接下来简单介绍最小生成树。

相关概念:

连通图: 对于无向图,任何两个顶点,他们之间都存在一条路径,则该无向图为连通图;

强连通图:对于有向图,图中任意两个顶点之间都存在一条有向路径,则该有向图为强连通图;

连通分量:非连通图中的各个连通子图成为该图的连通分量。



解决最小生成树的方法,用到的思想贪心,并查集,递归。

kruskal+并查集实现:

#include <iostream>
#include <string>
#include <cmath>
#include <algorithm>

#define BUG puts("here!!!");
using namespace std;
const int N = 5005;
int pre
;//空间复杂度
int n, m;
struct Node
{
int u, v;
int w; }
e
;
bool cmp(const Node a, const Node b)
{
return a.w < b.w;
}
void makeSet(int n)
{
for(int i = 0; i <= n; i++)
{
pre[i] = i;
}
}
int findSet(int a)
{
if(pre[a] == a)
return a;
return pre[a] = findSet(pre[a]);
}
void kruskal()
{
int fu, fv, sum = 0,count = 0;
sort(e, e+m, cmp);
makeSet(n);
for(int i = 0; i < m; i++)
{
fu = findSet(e[i].u);
fv = findSet(e[i].v);
if(fu != fv)
{
sum += e[i].w;
count++;
if(count == n-1) break;
pre[fv] = fu;
}
}
cout << sum << endl;
}
int main()
{
while(cin >> n, n)
{
cin >> m;
for(int i = 0; i < m; i++)
{
cin >> e[i].u >> e[i].v >> e[i].w;
}
kruskal();
}
}

kruskal是基于边的查找,先得对边排序,每次都查看当前最优,贪心的思想。

prim算法:参考
点击打开链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: