算法 排序算法之堆排序

package SortArith;
/**
 * 堆排序   构建最大堆,堆顶即为最大元素,每次取出最大元素后,再重新构建堆,这样再拿出次大值,循环往返
 * 注意:构建堆时需要调整每个非叶子节点,确定其为子堆的最大值;而调整堆时,只需要调整堆顶元素
 * 特例1:若所给待排序数组array本身已是最大堆类型{9,7,8,6,1,4,5,2,3},可不进行构建堆,即可省去第一个for循环过程
 * 特例2:若所给待排序数组array本身仅第一个元素待调整{-9,7,8,6,1,4,5,2,3},
 * 可省去第一个for循环过程, 而调用adjustHeap(array,0,array.length-1),调整第一个元素即可;
 * 时间复杂度:O(nlogn),其中构建堆为O(n),每次调整堆为logn
 * 不稳定排序  适合个数较多的排序
 * @author lwk
 *
 */
public class HeapSort {
     public static void main(String[] args) {
    	int[] array={-9,7,8,6,1,4,5,2,3};
 		heapSort(array);
 		for(int i=0;i<array.length;i++){
 			System.out.print(array[i] + " ");
 		}
	 }
     
     public static void heapSort(int[] array){
    	 if(array == null || array.length == 0){
    		 return; 
    	 }
    	 //从下往上,从右往左,依次调整各个非叶子节点,从而构建最大堆
    	 for (int i = array.length/2-1; i >= 0; i--) {
			 adjustHeap(array,i,array.length-1);
		 }
    	 //adjustHeap(array,0,array.length-1);
    	 //此时堆顶为最大值
    	 for (int i = array.length-1; i >=0; i--) {
			  //将堆顶元素逐步取出,与数组末尾值交换
    		 //第一次循环结束,数组末尾为最大值,之后每次循环得到数组的次大值
    		 int temp = array[0];
    		 array[0] = array[i];
    		 array[i] = temp;
    		 //重新调整堆 调整元素为array[0]
    		 adjustHeap(array,0,i-1);
		 }
     }
     /**
      * 调整堆方法   待调整元素为array[index] 使 index - end 成为一个最大堆
      * @param array
      * @param index  待调整元素
      * @param end     
      */
     public static void adjustHeap(int[] array, int index, int end){
    	 //将有变动的元素与其下左右子节点反复比较,直至不再有元素交换或者已到叶子节点
    	 for (int i = 2*index+1; i <= end; i = 2*i + 1) {
    		 //比较左右节点的大小,找出较大的值
    		 //注意:i=end时,表示没有右子节点,因此无需比较
			 if(i < end && array[i] < array[i+1]){
				 //若右节点较大,则下标指向右节点
				 i++;
			 }
			 //若待调整元素本身为三者最大值则下面均不需要再调整,退出循环
			 if(array[index] > array[i]){
				 break;
			 }
			 //否则将最大值与父节点交换
			 int temp = array[i];
			 array[i] = array[index];
			 array[index] = temp;
			 //交换后,则下一个待调整元素为i处元素,因此下次父节点仍为array[index]
			 //此后i = 2*i + 1,为array[index]的左子节点
			 index = i;
		}
     }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值