• 排序算法之堆排序(优先队列)


    1、堆排序的堆,其实是一个 完全二叉树。既是一个结点要么是叶子结点,要么必定有左右两个子节点的树。

    2、堆有序:每个结点的值,都必须大于两个子节点。但是两个子结点的大小不作要求。

    3、一棵大小为N的完全二叉树,高度为lgN(层)。

    用数组实现堆,假设数组下标从0开始,下标为k的元素,它的左子树是2k+1,右子树是左子树+1,即2k+2

    一:由上至下的有序化(下沉)

    如果堆的有序状态,因为某个结点比它的两个子结点或者其中之一小而打破了,那么可以通过与两个子结点中的较大者来交换。

    交换后可能会在子结点处打破原有序状态,那么只需要继续下沉,直至叶子结点。

    因为是在子树中做交换,对树的其他分支并没有影响。

    //下沉维护堆
    	public static void sink(int[]a,int k,int N){
    		
    		
    		
    		while(2*k+1<=N){
    			
    			
    			int j = 2*k+1;//左孩子的下标
    			
    			//j<N,说明存在右孩子
    			//a[j]<a[j+1],左孩子小于右孩子
    			if(j<N&&a[j]<a[j+1]) 
    				j++;
    			
    			//如果根结点并没有小于他的孩子,不用下沉了
    			if(!(a[k]<a[j]))
    				break;
    			
    			//否则
    			Example.exch(a, k, j);
    			
    			//交换后,更改当前,继续下沉
    			k=j;
    			
    			
    		}//end while
    		
    		
    		
    	}//end sink

    二:下沉实现的堆排序(原地排序)

    1、构建堆

    对于一个普通的数组,我们可以将他看成一个无序的堆。

    要使用堆排序,第一步就要将该数组构造成一个有序堆。

    一个简单的思想是,创建一个新数组,通过堆的插入元素方法,一个一个插入原数组的元素,进而完成一个新堆。

    其实并不需要,我们只要将前N/2的元素,下沉到合适的位置即可,此时堆即有序,后N/2全是叶子结点,无需下沉。

    2、下沉排序

    根据定义,根结点,既是数组的0位元素,永远是有序堆的最大值。

    所以我们只需要将它和数组最后一个元素交换位置,再将大小为N-1的数组(除去最后一个元素,因为他是最大值,放在最后),从新构建成一个新堆即可。怎么构建呢?就是把新的0号元素下沉到适合的位置。

    如此往复,即可得到一个有序的数组。

    //下沉排序
    	public static void sort(int []a){
    		
    		
    		//构建堆
    		//一开始可以将数组看作无序的堆
    		//将从下标为N/2开始一直到0的元素下沉到合适的位置即可。N/2后面的元素,其实都是叶子结点,无需下沉。
    		int N = a.length-1;
    		
    		for(int k = N/2;k>=0;k--){
    			
    			sink(a,k,N);
    			
    		}
    		
    		
    		
    		
    		//下沉排序
    		//堆的根结点永远是最大值,我们只需将最大值和最后一位的元素互换位置。然后再维护一个除原最大结点以外的N-1的堆,再将新堆的根节点放在倒数第二的位置。如此反复
    		
    		while(N>0){
    			
    			Example.exch(a, 0, N--);
    			sink(a,0,N);
    			
    		}
    		
    		
    	}//end sort
    

    时间复杂度:

    主要是下沉,其实下沉的时间复杂度非常直观,每次下沉,结点的高度-1,一棵树的高度是lgN,所以从0号位下沉到最后一位(最坏情况),也只是lgN。

    后面我们在下沉排序里面对每个元素其实都进行了下沉,所以总的来说是NlgN。

    空间复杂度:

    我们在该算法中,并没有用到临时变量或者新建的数组,所以不需要额外的空间。复杂度是常数。

    稳定性:

    不稳定

  • 相关阅读:
    前端常用模板引擎- artTemplate
    Vue-多级组件嵌套传值
    echarts图表常用到的设置
    react-基础入门分享
    vue中 export const 和 export default的区别
    vue安装依赖报错
    nvm-node版本控制工具
    gulp-入门
    vue 中使用 iconfont
    c3中基本动画
  • 原文地址:https://www.cnblogs.com/wzben/p/6151670.html
Copyright © 2020-2023  润新知