排序算法-堆排序

7 堆排序

基本思想

堆排序是一种树形选择排序,是对直接选择排序的有效改进。html

堆的定义下:

具备n个元素的序列(h1,h2,...,hn),当且仅当知足(hi>=h2i,hi>=2i+1)或(hi<=h2i,hi<=2i+1) (i=1,2,...,n/2)时称之为堆。在这里只讨论知足前者条件的堆。由堆的定义能够看出,堆顶元素(即第一个元素)必为最大项(大顶堆)。彻底二 叉树能够很直观地表示堆的结构。堆顶为根,其它为左子树、右子树。java

思想:

初始时把要排序的数的序列看做是一棵顺序存储的二叉树,调整它们的存储序,使之成为一个堆,这时堆的根节点的数最大。而后将根节点与堆的最后一个节点交换。而后对前面(n-1)个数从新调整使之成为堆。依此类推,直到只有两个节点的堆,并对它们做交换,最后获得有n个节点的有序序列。从算法描述来看,堆排序须要两个过程,一是创建堆,二是堆顶与堆的最后一个元素交换位置。因此堆排序有两个函数组成。一是建堆的渗透函数,二是反复调用渗透函数实现排序的函数。算法

示例:

  • 首先将序列构建称为大顶堆;(这样知足了大顶堆那条性质:位于根节点的元素必定是当前序列的最大值)

ErRrLt.png

  • 取出当前大顶堆的根节点,将其与序列末尾元素进行交换;(此时:序列末尾的元素为已排序的最大值;因为交换了元素,当前位于根节点的堆并不必定知足大顶堆的性质)
  • 对交换后的n-1个序列元素进行调整,使其知足大顶堆的性质;
    ErRDsI.png
  • 重复2.3步骤,直至堆中只有1个元素为止

实现

/**
 * 创建堆
 * @param a 待建的数组
 * @param lastIndex 须要创建的数组的最后一个元素(控制须要创建堆的长度)
 */
private void buildMaxHeap(int[] a, int lastIndex){
    // 从lastIndex处节点(最后一个节点)的父节点开始
    for(int i = (lastIndex-1)/2; i >=0 ; i--){
        // k保存正在判断的节点
        int k=i;
        // 若是当前的节点的子节点存在
        while (k*2+1<=lastIndex){
            // biggerIndex 为最大值的索引,先将其赋值为左子节点
            int biggerIndex = k*2+1;
            // 若是存在右子节点,则须要比较其大小
            if(biggerIndex < lastIndex){
                // biggerIndex始终为最大的子节点。
                if(a[biggerIndex + 1] > a[biggerIndex]){
                    biggerIndex++;
                }
            }
            // 若是k节点的值小于其较大的子节点的值,则须要交换他们
            if(a[biggerIndex] > a[k]){
                swap(a, biggerIndex, k);
                // 交换后的左子节点,、
                // 有可能小于他本身的子节点,
                // 因此须要从新进行比较排序,
                // 保证最小值在下面的节点
                k = biggerIndex;
            } else {
                break;
            }
        }
    }
}

/**
 * 交换
 */
private void swap(int[] a, int i, int j){
    int temp = a[i];
    a[i] = a[j];
    a[j] = temp;
}

public void heapSort(int[] a){
    for(int i=0; i<a.length-1; i++){
        buildMaxHeap(a, a.length-1-i);
        swap(a, 0, a.length-1-i);
    }
}

@Test
public void heapTest(){
    int[] a={7,5,3,2,9,10,8,4,6,1};
    heapSort(a);
    System.out.println(Arrays.toString(a));
}
复制代码

参考:
必须知道的八大种排序算法【java实现】(二) 选择排序,插入排序,希尔算法【详解】
数据结构常见的八大排序算法(详细整理)数组

相关文章
相关标签/搜索