堆排序的基本思想
堆排序是利用堆这种数据结构而设计的一种不稳定的排序算法,时间复杂度O(N*logN),额外空间复杂度O(1),堆排序有以下特点:
- 堆的数据结构:完全二叉树;
- 二叉树每个节点的值都大于等于其左右子树节点的值,称为大顶堆,用来升序排序;
- 二叉树每个节点的值都小于等于其左右子树节点的值,称为小顶堆,用来降序排序;
堆排序的实现步骤
- 利用元素下沉的方法构建一个大顶堆:从第一个父节点开始遍历,若父节点小于左(右)子节点,则父子节点交换,并继续向下遍历,直到所有子节点都小于父节点,则大顶堆构建完成;
- 此大顶堆的首元素即为数组最大值,将其与数组尾元素交换,即数组下标n-1元素已有序;
- 将待排数组缩短一位,对下标0至n-2的元素重复以上两步骤,直到数组元素个数为1,此时数组升序排序完成。
C++代码实现
#include <iostream>
#include <time.h>
#include <algorithm>
using namespace std;
/*排序方法类*/
class MySort {
public:
int n;
int* A;
//构造函数 ,便于挑选不同的排序方法
MySort(int N) {
this->n = N;
A = new int[this->n];
this->SetArray();
}
//随机初始化数组
void SetArray() {
srand(time(0));
for (int i = 0; i < n; i++) {
A[i] = rand() % 100 + 1;
}
}
//打印数组
void Print() {
for (int i = 0; i < n; i++) {
cout << A[i] << " ";
}
cout << endl;
}
//两数交换
void Swap(int &a, int &b) {
int c = a;
a = b;
b = c;
}
//堆排序
void heap_sort(int *A, int n){ //初始化堆,从最后一个父节点开始调整
for (int i = (n - 1) / 2; i >= 0; i--) //最后一个父节点位置在数组(n-1)/2处
heapify(A, i, n - 1);
//把堆顶元素和数组最后一个元素交换,然后重新构建堆,直到排序完成
for (int i = n - 1; i > 0; i--) {
Swap(A[0], A[i]);
heapify(A, 0, i - 1); //数组缩减一个尾元素,继续构建
}
}
void heapify(int *A, int start, int end) {
//确定父节点和左子节点的数组下标(左子节点+1即为右子节点)
int dad = start;
int son = dad * 2 + 1;
while (son <= end) {
//先比较两个子节点大小,选择大的
if ((son + 1 <= end) && (A[son] < A[son + 1]))
son++;
//若父节点大于此子节点,说明调整完毕,直接跳出函数
if (A[dad] > A[son])
return;
//否则交换父子节点,再继续子节点和孙节点的比较
Swap(A[dad], A[son]);
dad = son;
son = dad * 2 + 1;
}
}
};
int main(){
//初始化数组
int N;
cout << "请输入数组长度:";
cin >> N;
MySort sort(N); //构造排序方法类
cout << endl;
cout << "获得"<<N<<"位随机数组:" ;
sort.Print();
sort.heap_sort(sort.A, N);
cout << "堆排序后:";
sort.Print();
cout << endl;
return 0;
}
代码验证: