算法笔记19:堆排序

126 阅读1分钟

复习一下所有排序里我个人最不熟悉的堆排序。这里拿大顶堆为例。

堆排序使用的是堆的性质。在完全二叉树中,堆的每一个节点的值都是比它的两个子节点要大。所以利用这个特性,构建堆就可以找到整棵二叉树中的最大的数。这样不断重复,就可以一步步进行排序。

代码如下:

const heapify = (arr, len, i) => {
  let largest = i;
  // for complete binary tree, the index of children can be calculated
  const l = i * 2 + 1;
  const r = i * 2 + 2;
  
  // figure out which one is the largest between
  // current node, its left child and right child.
  if (l < len && arr[l] > arr[largest]) {
    largest = l;
  }
  if (r < len && arr[r] > arr[largest]) {
    largest = r;
  }
  
  // when current situation is not valid, it needs to swap nodes
  if (largest !== i) {
    const t = arr[i];
    arr[i] = arr[largest];
    arr[largest] = t;

    // heapify must go on, because this swap may be not finished
    heapify(arr, len, largest);
  }
}

const heapSort = (arr) => {
  const len = arr.length;
  // start the heapify from the first non-leaf node
  for (let i = Math.floor(len / 2) - 1; i >= 0; i--) {
    heapify(arr, len, i);
  }

  // start from the last position in the array
  for(let i = len - 1; i >= 0; i--) {
    // currently, the first element is the largest
    const t = arr[0];
    // swap the largest with current index
    arr[0] = arr[i];
    arr[i] = t;
    
    // continue to heapify, because we moved a new element to the root
    // but we only need to heapify a part of the array
    // because larger elements are already in the right places
    heapify(arr, i, 0);
  }
}