堆是一颗完全二叉树,所谓二叉树就是子节点从左到右是满的,不一定完全满,可以是部分满,如:下面的左边就是完全二叉树,而右边就不是。
    堆排序 - 图1
    而完全二叉树我们可以看成一个数组:[1,2,3,4,5,6,7]
    而左节点可以看成是: 2i+1;
    右节点可以看成: 2i+2;
    父节点可以看成:( i-1)/2

    堆分为大根堆、小根堆。
    大根堆就是:一颗树的每个子树的最大值就是树的头节点。
    小根堆就是:一棵树的每个子树的最小值就是树的头节点。
    用户输入一堆数字,heapsize为0,第一个树进来,一定是大根堆,接着再进来一个数,heapsize+1为1,跟父节点比较,如果比父节点大,就跟父节点交换位置,如果比父节点小,那么1的位置就为这个数,以此类推。父节点的位置为 (i-1)/2。

    1. // 找出大根堆的最大值即:第一个数,
    2. // 同时将这个数移走,使原来大根堆的还是大根堆
    3. function heapify(arr,index,heapSize) {
    4. let left = index*2 + 1; // 左孩子的下标
    5. while(left < heapSize){ // 当下方有孩子时
    6. // left+1即右孩子,即如果右孩子存在,跟左孩子比较,找出更大的,larges记录的是下标
    7. let largest = left + 1 < heapSize && arr[left+1] > arr[left] ? left+1 : left;
    8. // 父亲和较大孩子做比较,找出值更大的,把下标给largest
    9. if(largest === index){ // 如果就是父亲,那么它就是大根堆
    10. break;
    11. }
    12. swap(arr,largest,index); // 如果不是,那么就交换位置
    13. index = largest; // 来到较大孩子的位置
    14. left = index*2 + 1; // 较大孩子的左节点
    15. }
    16. }