堆排序算法

堆排序利用了大根堆(或小根堆)堆顶记录的 关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。
(1)用大根堆排序的基本思想
① 先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区
② 再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key
③由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。
……
直到无序区只有一个元素为止。
package com.zhangyao;
public class HeapSort {
	public static void main(String[] args) {
		int[]s={16,4,10,14,7,9,3,2,8,1};
		maxHeapSort(s);
		for(int cc=0;cc<s.length;cc++){
			System.out.print(s[cc]+" ");
		}
	}
	public static void buildMaxHeap(int a[],int n){    // 建最大堆
		for(int i=n/2-1;i>=0;i--){                     // a[n/2...n]都是树中的叶子,因此可以看成只含一个元素的堆 
			maxHeap(a,i,n);
		}
	}
	public static void maxHeap(int a[],int i,int n ){ // 保持最大堆,时间复杂度为:在高度为h的节点上时间为:O(h)
		int left=(i<<1)+1;                            // 左节点
		int right=(i<<1)+2 ;                          // 右节点
		int largest=0;                                // 存放最大节点的下标
		if(left<=n&&a[left]>a[i]){
			largest=left;
		}else{
			largest=i;
		}
		if(right<=n&&a[right]>a[largest]){
			largest=right;
		}
		if(largest!=i){
			int temp=a[i];
			a[i]=a[largest];
			a[largest]=temp;
			maxHeap(a,largest,n);                     // 递归子树,使交换后子树保持最大堆性质
		}
	}
	public static void maxHeapSort(int s[]){
		buildMaxHeap(s,s.length-1);                  //    建立最大堆,时间复杂度  O(n)
		for(int i=s.length-1;i>0;i--){               //    调换根元素和最后一个节点,n-1调用中每一次时间代价为:O(lg(n))
			int tempq=s[i];
			s[i]=s[0];
			s[0]=tempq;
			maxHeap(s,0,i-1);                        //     剔除最后一个节点,使剩下的保持最大堆
		}
	}
}
结论: 选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,而冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值