堆排序的JAVA实现和性能分析

package Sort;  
import java.util.Arrays;  
 
public class heapsort {  
  
    private static int parentIdx(int childIdx) {  //返回父节点下标
        return (childIdx - 1) / 2;  //索引从0开始, 注意childIdx=0时返回0  
    }  
  
    private static int leftChildIdx(int parentIdx) {  //返回左孩子下标
        return parentIdx*2 + 1;  
    }  
    
    //构建大顶堆
    private static void buildMaxHeap(int[] datas) 
    {  
        int lastIdx = datas.length -1;  //最后一个元素下标
        for(int i=parentIdx(lastIdx); i>=0; i--) // 最外层循环; i初始为最后一个元素的父节点下标,通过控制i的大小来逐步向上构建大顶堆
        {  
            int k = i;  // 第一个父亲节点i暂存于k中
            /*boolean isHeap = false;*/  
            
            while(/*!isHeap && */leftChildIdx(k) <= lastIdx) //获得较大孩子元素下标
             {  //判断是否有孩子
                int biggerChild = leftChildIdx(k);  
                if(biggerChild < lastIdx)                	
                 {    //有两个孩子  
                     if(datas[biggerChild] <= datas[biggerChild+1]) 
                       //j+1 比较大, 选择大的  
                    	 biggerChild++;//j总是保存较大子节点的索引                          
                 }  
  
              if(datas[k] > datas[biggerChild]) 
               {    //父的比较大  
                    /*isHeap = true;*/  
                    break;  
               } 
              else 
               {  
                    swap(datas, k, biggerChild);  //较大孩子元素和父亲元素交换
                    k = biggerChild;  //将biggerIndex(j)赋予k,开始while循环的下一次循环,重新保证k节点的值大于其左右孩子(因为父节点元素发生变化)
               }  
             }  
        }  
    }  
  
    //保持大顶堆
    private static void maintainMaxHeap(int[] datas, int lastIdx) {  
        int k = 0;  //从根节点开始
        while(k <= parentIdx(lastIdx)) {  //终止条件为最后一个元素的父节点
            int biggerChild = leftChildIdx(k);  
            if(biggerChild < lastIdx) {    //有两个孩子  
                if(datas[biggerChild] <= datas[biggerChild+1]) { //j+1 比较大, 选择大的  
                	biggerChild++;  
                }  
            }  
            if(datas[k] < datas[biggerChild]) {    //父结点比较小  
                swap(datas, k, biggerChild);  
                k = biggerChild;  
            } else {  
                break;  //跳出while循环体(所有子树都符合大根堆结构)
            }  
        }  
    }  
  //排序过程
    public static int[] sort(int[] datas) {  
        buildMaxHeap(datas);  //由datas构建大顶堆
        int lastIdx = datas.length - 1;//获取最后一个元素下标  
        while(lastIdx > 0) {  
            swap(datas, 0, lastIdx);  //交换根元素和最后一个元素
            lastIdx--;  
            if(lastIdx > 0) {  
                maintainMaxHeap(datas, lastIdx);  //维持大顶堆(实际上是将最大的放到树根处)
            }  
        }  
        return datas;  //此时datas已由小到大排序完成
    }  
    //交换数组中的两个元素
    public static void swap(int [] a,int k,int j)
    {
    	int tmp;
    	tmp=a[k];
    	a[k]=a[j];
    	a[j]=tmp;
    }
  
    public static void main(String[] args) {  
        int[] datas = {11,2,5,1,3,4,9,2,7,6,5};//{2, 9, 3, 7, 8, 6, 4, 5, 0, 1};  
  
        /*buildMaxHeap(datas); 
        System.out.println(Arrays.toString(datas));*/  
  
        sort(datas);  
        System.out.println(Arrays.toString(datas));  

  
    }  
  
  
}  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值