堆排序

1.堆排序

  • 堆是一个完全二叉树。
  • 完全二叉树: 二叉树除开最后一层,其他层结点数都达到最大,最后一层的所有结点都集中在左边(左边结点排列满的情况下,右边才能缺失结点)。
  • 大顶堆:根结点为最大值,每个结点的值大于或等于其孩子结点的值。
  • 小顶堆:根结点为最小值,每个结点的值小于或等于其孩子结点的值。

对二叉树做升序排序,总共分为三步:

1.将初始二叉树转化为大顶堆(heapify)(实质是从第一个非叶子结点开始,从下至上,从右至左,对每一个非叶子结点做shiftDown操作),此时根结点为最大值,将其与最后一个结点交换。

2.除开最后一个结点,将其余节点组成的新堆转化为大顶堆(实质上是对根节点做shiftDown操作),此时根结点为次最大值,将其与最后一个结点交换。

3.重复步骤2,直到堆中元素个数为1(或其对应数组的长度为1),排序完成。


var len;
    function buildMaxHeap(arr) {   //建堆
        len = arr.length;
        // [n/2-1]表示的是最后一个有子节点 (本来是n/2(堆从1数起),但是这里arr索引是从0开始,所以-1)
        for (var i = Math.floor(len/2)-1; i>=0; i--) {
            maxHeapify(arr, i);
        }
        //对每一个节点(非叶节点),做堆调整
    }
    function maxHeapify(arr, i) {     //堆调整
        var left = 2*i+1,
            right = 2*i+2,
            largest = i;   //i为该子树的根节点
 
        if (left < len && arr[left] > arr[largest]) {
            largest = left;
        }
 
        if (right < len && arr[right] > arr[largest]) {
            largest = right;
        }
 
        if (largest != i) {  //即上面的if中有一个生效了
            swap(arr, i, largest);  //交换最大的为父节点
            maxHeapify(arr, largest);  //交换后,原值arr[i](往下降了)(索引保存为largest),
            //作为根时,子节点可能比它大,因此要继续调整
        }
    }
    function swap(arr, i, j) {
        var temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
    function heapSort(arr) {
        buildMaxHeap(arr);
        for (var i = arr.length-1; i > 0; i--) {
            swap(arr, 0, i);
            len--;
            maxHeapify(arr, 0);
        }
        return arr;
    }


原文地址:https://www.cnblogs.com/hff-syt/p/12454529.html