堆排序C++实现

堆排序的基本思想

堆排序是利用堆这种数据结构而设计的一种不稳定的排序算法,时间复杂度O(N*logN),额外空间复杂度O(1),堆排序有以下特点:

  1. 堆的数据结构:完全二叉树;
  2. 二叉树每个节点的值都大于等于其左右子树节点的值,称为大顶堆,用来升序排序;
  3. 二叉树每个节点的值都小于等于其左右子树节点的值,称为小顶堆,用来降序排序;

堆排序的实现步骤

  1. 利用元素下沉的方法构建一个大顶堆:从第一个父节点开始遍历,若父节点小于左(右)子节点,则父子节点交换,并继续向下遍历,直到所有子节点都小于父节点,则大顶堆构建完成;
  2. 此大顶堆的首元素即为数组最大值,将其与数组尾元素交换,即数组下标n-1元素已有序;
  3. 将待排数组缩短一位,对下标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;
}

代码验证:

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LiuZuqiang_3027

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值