堆排序算法

1.前言

堆排序是时间复杂度 比 冒泡、选择、插入 都的排序算法
时间复杂度为0(N2
在学习堆排序,之前首先应当对二叉树有基本的了解,明白完全二叉树、大根堆等基本定义,这样有助于理解堆排序。

初学补充:
1.完全二叉树
定义: 一棵深度为k的有n个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同,则这棵二叉树称为完全二叉树。
如下图:
在这里插入图片描述
2.大根堆:
要求:
①根节点的关键字既大于或等于左子树的关键字值,又大于或等于右子树的关键字值。(根节点比左孩子、右孩子都大)
②为完全二叉树。(从左向右依次排满)
(即,每个节点都应当是当前树的最大值)

2.内容

1.简单实现

下面看一下如何实现堆排序:

#include <iostream>
using namespace std;
#include <algorithm>
void heapify(int a[],int i,int heapsize)
{
	int left = 2 * i + 1;      //找到左孩子
	while (left < heapsize)
	{
		int largest = left + 1 < heapsize && a[left + 1] > a[left] ? left + 1 : left;       //找到 左 右 孩子 中较大的
		largest = a[i] > a[largest] ? i : largest;        //再与父 比较
		if (largest == i)          //如果 父节点 已经最大(符合大根堆的要求,则不下沉)
		{
			break;
		}
		swap(a[largest], a[i]);     //交换节点

		i = largest;      //令 父节点为 largest 继续下沉
		left = 2 * i + 1;
	}
}

void Duipai(int a[],int n)
{
	if (n < 1)     //设置限制条件
		return;
	for (int i = n - 1; i >= 0; i--)     //先使数组为 大根堆
	{
		heapify(a, i,n);
	}
	int heapsize = n;
	swap(a[0], a[--heapsize]);     //让 头节点 和 尾节点 交换
	while (heapsize > 0)
	{
		heapify(a, 0, heapsize);   //再变为 大根堆
		swap(a[0], a[--heapsize]);  //再交换
	}
}

int main()
{
	int n;
	cin >> n;
	int* a = new int [n];
	for (int i = 0; i < n; i++)
		cin >> a[i];
	Duipai(a,n);
	for (int i = 0; i < n; i++)
		cout << a[i] << " ";
	delete[]a;
	delete[]b;
	return 0;
}

运行结果:
在这里插入图片描述

2.用对数器检验

单击了解 对数器

#include <iostream>
using namespace std;
#include <algorithm>
#include <ctime>
#include <cstdlib>
void heapify(int a[],int i,int heapsize)
{
	int left = 2 * i + 1;      //找到左孩子
	while (left < heapsize)
	{
		int largest = left + 1 < heapsize && a[left + 1] > a[left] ? left + 1 : left;       //找到 左 右 孩子 中较大的
		largest = a[i] > a[largest] ? i : largest;        //再与父 比较
		if (largest == i)          //如果 父节点 已经最大(符合大根堆的要求,则不下沉)
		{
			break;
		}
		swap(a[largest], a[i]);     //交换节点

		i = largest;      //令 父节点为 largest 继续下沉
		left = 2 * i + 1;
	}
}

void Duipai(int a[],int n)
{
	if (n < 1)     //设置限制条件
		return;
	for (int i = n - 1; i >= 0; i--)     //先使数组为 大根堆
	{
		heapify(a, i,n);
	}
	int heapsize = n;
	swap(a[0], a[--heapsize]);     //让 头节点 和 尾节点 交换
	while (heapsize > 0)
	{
		heapify(a, 0, heapsize);   //再变为 大根堆
		swap(a[0], a[--heapsize]);  //再交换
	}
}

int main()
{
	srand((unsigned int)time(NULL));    //设置随机数种子
	int n;
	n = rand() % 50+1;     //每一组数字个数 为 1~50
	int* a = new int [n];
	int* b = new int[n];

	for (int i = 0; i < n; i++)
		a[i]=rand()%1000+1;         //每一个数字为 1~1000
	//令 a[] b[]数组数据相同
	for (int i = 0; i < n; i++)
		b[i] = a[i];
	Duipai(a,n);
	sort(b, b + n);
	int testtime = 10000;
	int flag = 1;
	while (testtime--)
	{
		int i;
		for (i = 0; i < n; i++)
		{
			if (a[i] != b[i])
				break;
		}
		if (i < n)
			flag = 0;
	}
	if (flag)     //flag未被改动
		cout << "success!" << endl;
	else
	{
		cout << "fail!" << endl;
		/*for (int i = 0; i < n; i++)
			cout << a[i] << " ";
		cout << endl;
		for (int i = 0; i < n; i++)
			cout << b[i] << " ";*/
	}
	delete[]a;
	delete[]b;
	return 0;
}

在这里插入图片描述

3.总结

堆排序最重要的是理解堆的思想,以后会有很大帮助

4.更新日志

2022.4.28 整理上传
欢迎评论留言、指正~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值