堆排序——java

堆排序:
时间复杂度:O(n*log2(n))
空间复杂度:O(1)
不稳定
核心代码:

import java.util.Arrays;

/**
 * 堆排序
 * @author jin
 */
public class Heap {
    /**
     * 创建大顶堆
     * @param array
     * @param lastIndex
     */
    public static void createMaxHeap(int[] array, int lastIndex) {
        for (int i = (lastIndex - 1) / 2; i >= 0; i--) {
            int fatherIndex = i;
            while (fatherIndex * 2 + 1 <= lastIndex) { // 如果当前父节点有子节点的话
                int biggerIndex = fatherIndex * 2 + 1;
                if (biggerIndex < lastIndex) {
                    if (array[biggerIndex] < array[biggerIndex + 1]) {
                        biggerIndex++;
                    }
                }
                if (array[biggerIndex] > array[fatherIndex]) {
                    swap(array, fatherIndex, biggerIndex);
                } else {
                    break;
                }
            }
        }
    }
    /**
     * 数组中元素进行交换
     * @param array
     * @param i
     * @param j
     */
    public static void swap(int[] array, int i, int j) {
        int tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }
    /**
     * main方法
     */
    public static void main(String[] args) {
        int[] a = { 1, 2, 56, 3, 55, 2, 66, 9, 0, 7 };
        for (int i = 0; i < a.length - 1; i++) {
            createMaxHeap(a, a.length - 1 - i);
            swap(a, 0, a.length - 1 - i);
        }
        System.out.println(Arrays.toString(a));
    }
}

堆排序,有两个步骤:
(1)先建一个大顶堆,
(2)然后堆顶与堆的最后一个元素进行交换。
步骤:
(1)建大顶堆:
大顶堆:所有的父节点的数都比子节点的数大。
大顶堆是通过数组进行存储的 ,例如:
堆的结构
在内存中的存储方式为:
存储方式
求某一子节点的父节点的索引:
(子节点索引-1)/2取整
建堆时,先从最后一个数开始,最后一个索引为lastIndex,其父节点为fatherIndex=(lastIndex-1)/2;如果该父节点有子节点的话,那么左节点为leftIndex=fatherIndex*2+1;
如果建大顶堆,也是从最后一个数开始,不过求子节点时,先假设左节点为最大的数biggerIndex=fatherIndex*2+1;如果biggerIndex

for(int i=(lastIndex-1)/2;i>=0;i--){//从后往前建立
    int fatherIndex=i;
    while(fatherIndex*2+1<=lastIndex){//如果当前父节点有子节点的话
        int biggerIndex=fatherIndex*2+1;//为左节点
        if(biggerIndex<lastIndex){
            if(a[biggerIndex]<a[biggerIndex+1]){
                biggerIndex++;//此时最大的数变为右节点
            }
        }
        if(a[biggerIndex]>a[fatherIndex]){//交换这两个索引的值的位置
        //这里用到了位运算,详细的以后会写
            a[fatherIndex]=a[biggerIndex]^a[fatherIndex];
            a[biggerIndex]=a[biggerIndex]^a[fatherIndex];
            a[fatherIndex]=a[biggerIndex]^a[fatherIndex];
        }else{
            break;
        }
    }
}

(2)然后堆顶与堆的最后一个元素进行交换。
这里就开始进行排序了,交换完成后,就实现了从小到大的排列。

猜你喜欢

转载自blog.csdn.net/levi_moon/article/details/51472986