Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

【经典排序算法】堆排序 #2

Open
Enivia opened this issue May 31, 2021 · 0 comments
Open

【经典排序算法】堆排序 #2

Enivia opened this issue May 31, 2021 · 0 comments
Labels

Comments

@Enivia
Copy link
Owner

Enivia commented May 31, 2021

堆排序

堆总是满足以下性质:

  • 堆中某个结点的值总是不大于或不小于其父结点的值
  • 堆总是一棵完全二叉树

将根结点最大的堆叫做最大堆/大根堆,根结点最小的堆叫做最小堆/小根堆。

堆排序的核心就是小根堆/大根堆的构造。

原理

以升序为例,具体流程为:

  1. 将待排序的序列构造为小根堆
  2. 取走根节点,即为最小值
  3. 继续将剩余节点构造为小根堆后重复上述操作,直到排序完成

图解

初始无序数组 [8, 4, 5, 7, 1, 3, 2, 6, 9],对应的树结构如下

image

下面开始构造最小堆。找到最后一个非叶子节点,从左到右与其子节点进行比较,若比其子节点大,则进行交换。

image

完成后,找到倒数第二个非叶子节点,继续排序。

image

对所有根节点重复上述操作。

image

image

排序过程

代码实现

以构造最大堆为例:

function swap(arr, i, j) {
  var temp = arr[i];
  arr[i] = arr[j];
  arr[j] = temp;
}

/** 调整堆结构 */
function minHeapify(arr, index, size) {
  var left = index * 2 + 1;
  var right = index * 2 + 2;
  var root = index;

  if (left < size && arr[left] < arr[root]) {
    root = left;
  }
  if (right < size && arr[right] < arr[root]) {
    root = right;
  }
  if (root !== index) {
    swap(arr, root, index);
    minHeapify(arr, root, size);
  }
}

/** 构造最小堆 */
function buildMinHeap(arr, size) {
  var start = Math.floor(size / 2) - 1;
  for (var i = start; i >= 0; i--) {
    minHeapify(arr, i, size);
  }
}

/** 排序 */
function sort(nums) {
  const result = []
  let len = nums.length;
  buildMinHeap(nums, len);
  for (let i = len - 1; i >= 0; i--) {
    swap(nums, i, 0);
    result.push(nums[len - 1]);
    len -= 1;
    buildMinHeap(nums, len);
  }
  return result
}
@Enivia Enivia added the 算法 label May 31, 2021
@Enivia Enivia changed the title 堆排序 【经典排序算法】堆排序 Nov 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant