zoukankan      html  css  js  c++  java
  • 并查集的定义

    并查集:一种维护集合的数据结构

    一、合并onion

    二、查找find

    初始化、查找(路径压缩)、合并

    堆:本质是二叉树

    //并查集的复习
    //堆的复习
    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<stack>
    #include<cstdio>
    #include<queue>
    #include<map>
    #include<vector>
    #include<set>
    using namespace std;
    const int maxn=1010;
    const int INF=0x3fffffff;
    //并查集的数据结构:数组
    int fa[maxn];
    //操作:查找、合并
    //查找的优化:路径压缩
    int findfa(int x){
    	if(x!=fa[x]) fa[x]=findfa(fa[x]);
    	return fa[x];
    }
    //合并其实有也优化,有时候并查集有权值的时候会有选择性的合并,根据权值大小合并 
    void ini(int a,int b){
    	int fa1=findfa(a);
    	int fa2=findfa(b);
    	if(fa1!=fa2) fa[fa2]=fa1;
    }
    //并查集产生的集合:一棵树
    
    //堆:
    //a heap is a specialized tree-based data structure(树)、并查集、堆的实质其实都可以是树 
    //一般的快速数据结构:优先队列:
    //优先队列默认:大顶堆 (不用自己写函数) 
    priority_queue<int> q1;
    //小顶堆
    priority_queue<int,vector<int>,greater<int> > q2;
    //跟一般的数据结构(需要自己写函数的那种) 
    
    //需要自己写函数 
    int heap[maxn];  //just like堆 
    //但是掌握堆的自顶向上和自底向上的两种写法是很重要的
    //建堆的过程:自上向下调整,但是需要倒着枚举调整,调整所有的非叶子节点,从n/2到1,倒着调整,但是调整是自顶向下的
    //包括删除节点的时候:删除堆顶元素,用最后一个元素覆盖第一个,然后调整downjust(1,n)
    void downadjust(int low,int high){ //向下调整:删除、建堆、堆排序 
    	int i=low,j=2*i;
    	while(j<=high){
    		//如果有孩子存在,且有孩子的值大于左孩子的值,就像后移,然后再跟i比较大小
    		if(j+1<=high&&heap[j+1]>heap[j]) j++;
    		if(heap[j]>heap[i]){
    			//如果孩子比爸爸大,就要交换
    			swap(heap[j],heap[i]);
    			i=j;
    			j=2*i; 
    		} 
    		else break; //不然就退出 
    	}
    } 
    void create(){
    	for(int i=1;i<=n;i++) cin>>heap[i];
    	for(int i=n/2;i>=1;i--) downadjust(i,n);
    }   //倒着调整:这样才能满足每个节点都是以他为父节点的最大值 
    //删除堆顶元素
    void del(){
    	heap[1]=heap[n--];
    	downadjust(1,n);  //调整堆顶 
    } 
    //添加一个元素的时候:添加再最后面,然后自底向上调整 
    void upadjust(int high,int low){
    	int i=high,j=high/2;
    	while(j>=low){
    		//总是和父亲比较的话,就不存在j++或者j--了,直接比较就可以了
    		if(heap[j]<heap[i]){
    			swap(heap[j],heap[i]); 
    			i=j;  //如果父亲比小的话,就交换 
    			j/=2;
    		} 
    		else break;
    	}
    }
    void insert(int x){
    	heap[++n]=x;  //添加再末尾 
    	upadjust(n,1);
    }
    //删除堆顶,添加末尾
     
    //堆排序
    //由于堆中堆顶元素是确定的最大的,所以每次都去堆顶元素和最末尾的元素交换,然后从堆顶进行自顶向下的调整
    //这样每次都取出了最大堆顶元素,而且对的范围也在缩小
    void heapsort(){
    	create(); //先建堆 
    	for(int i=n;i>1;i--) {
    		swap(a[i],a[1]);  //交换 
    		downadjust(1,i-1);  //范围再缩小 
    	}
    	for(int i=1;i<=n;i++) cout<<heap[i]<<" ";
    	//自小到大的序列 
    } 
    

      

  • 相关阅读:
    常见排序算法的实现
    Never-build package 'XXXX' requires always-build package 'EhLib70'
    自制的七个C,总结的太好了
    那些有影响力的语言
    数海笔记(0)-程序员为什么要学数学
    linux 多线程编程笔记
    双指数边缘平滑滤波器用于磨皮算法的尝试。
    对于树的序列化,用了stream,很好
    很聪明的解法
    按窗口获得最大数 和 中位数
  • 原文地址:https://www.cnblogs.com/shirlybaby/p/12274055.html
Copyright © 2011-2022 走看看