前端-堆排序 (选择排序)

  1. 堆排序

    • 小根堆: L[i] <= L[2i] && L[i] <= L[2i + 1]
    • 大根堆: L[i] >= L[2i] && L[i] >= L[2i + 1]
  2. 空间效率: O(1) 仅仅使用了常数个辅助单元
    时间效率: O(nlog2 n)
    稳定性: 不稳定

/**
 * 构建大根堆
 */
function buildMaxHeap(arr) {
  const len = arr.length - 1; // 因为arr[0] 暂存元素
  for (let i = parseInt(len / 2); i > 0; i--) {
    AdjustDown(arr, i)
  }
}

/*
 * 构建小根堆
 */

// 将元素i向下调整  形成大根堆
function AdjustDown(arr, k) {
  const len = arr.length - 1; // 因为arr[0] 暂存元素
  arr[0] = arr[k]; // arr[0] 暂存元素
  for (let i = 2 * k; i <= len; i *= 2) {
    if (i < len && arr[i] < arr[i + 1]) {
      i++;
    }
    // 筛选结束 表示当前节点已经在合适的位置上, 当前节点已经大于其所有的子节点
    if (arr[0] >= arr[i]) break;
    // 需要交换当前节点k和i的数据元素位置
    else {
      arr[k] = arr[i];
      k = i;
    }
  } // end for
  arr[k] = arr[0];
}

function HeapSort(arr) {
  const resultArr = [];
  const len = arr.length - 1;
  buildMaxHeap(arr)
  for (let i = len; i >= 1; i--) {
    // Swap(arr, i, 1);
    // 输出堆顶部的最大元素
    resultArr.push(arr[1])
    const tmp = arr[i]
    arr[i] = arr[1]
    // 将堆底部的元素放在顶部, 重新调整构造
    arr[1] = tmp;
    // 这里不能用slice
    arr.length = i;
    AdjustDown(arr, 1)
  } // end for
  return resultArr;
}

function buildMaxHeap_UP(arr) {
  const len = arr.length - 1; // 因为arr[0] 暂存元素
  for (let i = len; i > parseInt(i / 2); i--) {
    AdjustUp(arr, i);
  }
}

// 向上调整 形成大根堆
function AdjustUp(arr, k) {
  // var k = arr.length - 1;
  arr[0] = arr[k];
  let i = parseInt(k / 2);
  while (i > 0 && arr[i] < arr[0]) {
    arr[k] = arr[i];
    k = i;
    i = k / 2;
  } // end while
  arr[k] = arr[0];
}

const arr = [null, 53, 17, 78, 9, 45, 65, 87, 32];
// buildMaxHeap_UP(arr)

// buildMaxHeap(arr)
const resultArr = HeapSort(arr);

console.log(resultArr);
// console.log(arr.slice(1))

你可能感兴趣的:(前端-堆排序 (选择排序))