排序算法之堆排序

java实现堆排序

Posted by carm on July 11, 2016

排序算法之堆排序

java实现堆排序

快要考试了,复习了下排序算法,现对堆排序的实现过程作下详细记录。

概述

堆排序和插入排序一样,是一种原地排序算法;和归并排序一样,运行时间为O(nlgn)。二叉堆有两种,最大堆和最小堆,下面算法实现的是最大堆,即堆中最大元素存放在根节点。

算法实现

package Sort;
/**
 	 * Created by carm on 2016/7/10.
 	 * Heap.java
 	 */
public class Heap {
	public static void sort(int []a){
        int N = a.length;
        /**
         * build heap
         * 完全二叉树使用数组结构存储,设数组大小为N,数组下标以0开始
         * 因为叶节点可以看作是只含有一个元素的堆
         * 故循环以非叶节点作为开始节点;
         * 若数组大小为N,则 所有大于K =(N/2)-1的节点都是叶节点
         */
        for(int k=N/2-1; k>=0; k--){
            sink(a,k,N-1);
        }
        /**
         * HeapSort
         * 通过互换首末位置,将最大元素放到最终位置
         */
        while(N>1){
            swap(a,0,--N);
            sink(a,0,N-1);
        }
    }

    /**
     *
     * @param a
     * @param k
     * @param N 堆元素个数
     */
    private static void sink(int []a, int k, int N){
        /**
         * MAX-HEAPIFY
         * 数组下标以0开始,故左右孩子下标为2k+1与2k+2
         */
        while(2*k+1 <= N){
            int j= 2*k+1;
            if(j<N && a[j]<a[j+1]) j++; //比较左右孩子节点,找最大值,下标记为j
            if(a[k]>a[j])   break;
            swap(a,k,j);
            k = j;
        }
    }
    private static void swap(int[] a, int j, int i) {
        int t = a[j];
        a[j]=a[i];
        a[i]=t;
    }
}

测试代码

package Sort;
/**
 * Created by carm on 2016/7/10.
 * test.java
 	 */
public class test {
    public static void main(String []args){
        int []a = {12,43,23,18,49,36,50,9,3};
        Heap.sort(a);
        for(int e: a){
            System.out.print(" "+e);
        }
    }
}

运行结果

3 9 12 18 23 36 43 49 50

参考书籍

  1. 《算法导论》
  2. 《算法》第4版