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 整理上传
欢迎评论留言、指正~~