643 字
3 分钟
堆排序

堆排序(Heap sort)#

内容主要来自堆排序算法_阿顾同学的博客-CSDN博客_堆排序,有修改

准备知识#

满二叉树#

顾名思义,就是全满的都不空的二叉树

完全二叉树#

在满二叉树的基础上,从右下角开始缺省(即满二叉树的最下面一层的最右面开始依次缺省,倒数第二层都不行

大根堆 小根堆#

在完全二叉树的基础上,每个结点值都大于其左孩子和右孩子的值,叫大根堆。

每个结点值都小于其左孩子和右孩子的值,叫小根堆。

父结点 左右孩子索引#

父结点索引:n / 2 - 1

左孩子索引:2 * i + 1

右孩子索引:2 * i + 2

堆排序原理#

  1. 首先将待排序的数组元素构造成一个大根堆,此时,整个数组的最大值就是堆结构的顶端
  2. 将顶端的数与末尾的数交换,此时,末尾的数为最大值,剩余待排序数组的个数为n-1
  3. 将剩余n-1个数再构造成大根堆,再将顶端数与n-1位置的数交换,如此反复执行,便能得到有序数组

构造大根堆过程#

堆排序算法_阿顾同学的博客-CSDN博客_堆排序

升序排序(大根堆)代码:#

#include<stdio.h>
#include<iostream>
#include<vector>
using namespace std;
void Adjust(vector<int> &vec, int start, int end) {
int father = start;
int child = father * 2 + 1;
while (child <= end) {//child<=end的意义是这个孩子节点存在
if (child + 1 <= end && vec[child] < vec[child + 1]) {//右孩子存在,且右孩子大于左孩子
child++;
}
if (vec[child] > vec[father]) {//最大的子结点大于父亲则交换
swap(vec[child], vec[father]);
}
//交换后可能破坏了下面的结构,所以继续向下处理
father = child;
child = father * 2 + 1;
}
}
void Heap_sort(vector<int> &vec) {
int n = vec.size();
//创建最大堆,从最后一个结点的父结点开始
for (int i = n / 2 - 1; i >= 0; --i) {
Adjust(vec, i, n - 1);
}
//逐个交换,堆顶元素和待排序中的最后一个元素
for (int i = n - 1; i >= 0; --i) {
swap(vec[0], vec[i]);//交换堆顶元素和最后一个元素
Adjust(vec, 0, i - 1);//然后把剩下的待排序数组再处理成最大堆结构
}
}
int main() {
vector<int> vec = { 3, 6, 8, 5, 7 };
int n = vec.size();
Heap_sort(vec);
for (int i = 0; i < n; ++i) {
cout << vec[i] << " ";
}
return 0;
}
堆排序
https://fuwari.cbba.top/posts/堆排序/
作者
Chen_Feng
发布于
2023-02-19
许可协议
CC BY-NC-SA 4.0