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


    前言

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

    并查集

    参考文献《算法导论》,博客 http://blog.csdn.net/dm_vincent/article/details/7655764
    并查集包括三个操作:make_set,find_set,union_set。

    链表表示:

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


    树根表示:

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

    图的最小生成树

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

    相关概念:

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

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

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

      

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

    kruskal+并查集实现:

    #include <iostream>
    #include <string> 
    #include <cmath> 
    #include <algorithm>
    
    #define BUG puts("here!!!"); 
    using namespace std; 
    const int N = 5005; 
    int pre[N];//空间复杂度
    int n, m; 
    struct Node
    {    
    int u, v;   
    int w; }
    e[N];
    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算法:参考 点击打开链接

  • 相关阅读:
    IOS笔记-C语言中的字符串数组 指针
    IOS笔记-C语言中的指针与数组
    Entity Framework 知识点总结
    提升代码内外部质量的22条经验(转载)
    WPF 第一个创建的窗体会作为Application.Current.MainWindow
    重构的十个小技巧(转)
    WPF DataGrid自定义分页控件_实现下拉刷新数据
    使用qt生成安卓android运用
    关于开发省流量手机游戏的一些建议
    c++ com 在c#项目里面使用简单例子
  • 原文地址:https://www.cnblogs.com/snake-hand/p/3187031.html
Copyright © 2020-2023  润新知