堆是一颗完全二叉树,所谓二叉树就是子节点从左到右是满的,不一定完全满,可以是部分满,如:下面的左边就是完全二叉树,而右边就不是。
而完全二叉树我们可以看成一个数组:[1,2,3,4,5,6,7]
而左节点可以看成是: 2i+1;
右节点可以看成: 2i+2;
父节点可以看成:( i-1)/2
堆分为大根堆、小根堆。
大根堆就是:一颗树的每个子树的最大值就是树的头节点。
小根堆就是:一棵树的每个子树的最小值就是树的头节点。
用户输入一堆数字,heapsize为0,第一个树进来,一定是大根堆,接着再进来一个数,heapsize+1为1,跟父节点比较,如果比父节点大,就跟父节点交换位置,如果比父节点小,那么1的位置就为这个数,以此类推。父节点的位置为 (i-1)/2。
// 找出大根堆的最大值即:第一个数,// 同时将这个数移走,使原来大根堆的还是大根堆function heapify(arr,index,heapSize) {let left = index*2 + 1; // 左孩子的下标while(left < heapSize){ // 当下方有孩子时// left+1即右孩子,即如果右孩子存在,跟左孩子比较,找出更大的,larges记录的是下标let largest = left + 1 < heapSize && arr[left+1] > arr[left] ? left+1 : left;// 父亲和较大孩子做比较,找出值更大的,把下标给largestif(largest === index){ // 如果就是父亲,那么它就是大根堆break;}swap(arr,largest,index); // 如果不是,那么就交换位置index = largest; // 来到较大孩子的位置left = index*2 + 1; // 较大孩子的左节点}}
