您的位置:首页 > 理论基础 > 数据结构算法

数据结构和算法 堆排序 (图解堆调整)

2020-06-24 04:27 363 查看

什么是堆?

:是一种特殊的序列 并且 将该序列想象为 完全二叉树

元素满足

  • (ki <= k2i && ki <= k2i+1) 每个结点一定比它的左右孩子小 这种堆称为 最小化堆(小堆) (树根是最小的)
  • (ki >= k2i && ki >= k2i+1) 每个点一定比它的左右孩子大 这种堆称为 最大化堆(大堆) (树根是最大的)

堆排序(以最大化堆为例

堆调整:排序之前需要将序列调整为 (不满足时 与 左右孩子中较大的那一个进行交换) 从n/2向下取整个点开始由后向前调整直到满足堆条件为止。

排序

  1. 从堆顶取出最大元素 ,堆顶元素与堆的最后一个元素交换位置 (往后就不用考虑当前最后一个元素)。
  2. 对剩余的元素进行调整 , 调整选择剩下元素中的最大元素 (根与左右孩子中较大的那个进行交换直到满足条件为止)即 对进行堆调整。
  3. 重复以上过程 直到序列有序为止 (大堆升序)。

例子 (堆调整过程)

初始序列为:5 4 8 0 9 3 2 6 7 1

1.画出该序列完全二叉树

2.找到n/2向下取整的点 本例为 (9)从后往前逐个调整

  • 0 < 6 同时 0 < 7 因为 7 > 6 故 0 与 7 交换 ;满足条件 。

    8满足条件 继续 4 < 7 同时 4 < 9 因为 9 > 7 故 4 与 9 交换 ;满足条件。

  • 5 < 9 同时 5 < 8 因为 9 > 8 故 5 与 9 交换 ;此时 5 < 7 不满足 5与7 交换 ;此时 5 <
    6 不满足 5与6 交换;满足条件。

  • 堆排序

参考上述排序过程。

代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>

typedef long long ll;
using namespace std;

const int N = 1010;
int n;
int a[N];
void mheap(int a[],int x,int m)
{
int temp;
while((2*x <= m && a[x] < a[2*x]) || (2*x+1 <= m && a[x] < a[2*x+1])) // 小于左右孩子 并且  防止越界
{
temp = a[2*x] >= a[2*x+1]||2*x == m ? 2*x:2*x+1;  // 比较左右孩子取较大的那个,也可能存在只有左孩子
swap(a[x],a[temp]);
x = temp;
}
}

void heapsort(int a[],int len)
{
for(int i = len/2;i >= 1;i--)
mheap(a,i,len); //对n/2向下取整由后往前调整

for(int j = len;j >= 2;j--)
{
swap(a[1],a[j]);
mheap(a,1,j - 1); //对根节点调整
}
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0);
cin >> n;
for(int i = 1;i <= n;i++) cin >> a[i];
heapsort(a,n);
for(int i = 1;i <= n;i++)
cout << a[i] <<' ';
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: