排序算法(三)——堆排序

排序算法(三)


简介

  1. 堆排序是什么?
    像上篇的希尔排序是对直接插入排序算法的优化,堆排序是对选择排序的优化。
    因此其基本思想就是每次循环获取未被排序过数据中的最大值(或者最小值)。
    考虑到选择排序每次选出n个数据中的最值需要计算n-1次,因此堆排序的主要优化点就在于此。
    堆排序的复杂度为O(nlog2n)。

  2. 堆排序的基本步骤?
    首先从下向上构造大顶堆(或者小顶堆),即根节点元素总是大于(或者小于)其孩子节点的树结构;
    此时的根节点即为最大(最小)元素,将最值元素(第1个元素)与第i个元素交换;
    对剩余的i-1个元素重新构造大顶堆(或者小顶堆)。
    注:大小顶堆的构造无需像前述的树结构构造一样复杂,有父节点、子节点、权重等。此处的大小顶堆只需通过下标来判断其位置即可。
    父节点和子节点的下标关系为i2i以及2i+1(1<=i<=n)。


代码

代码如下:

#include <iostream>
using namespace std;
void swap(int k[], int i, int j)
{
    int tmp = k[i];
    k[i] = k[j];
    k[j] = tmp;
}
void HeapAdjust(int k[], int s, int n)
{
    int tmp = k[s];
    for (int i = 2*s; i <= n; i *= 2)
    {
        if (i < n and k[i] < k[i+1])
        {
            i++;
        }
        if (tmp > k[i])
            break;
        k[s] = k[i];
        s = i;
    }
    k[s] = tmp;
}
void HeapSort(int k[], int n)
{
    for (int i = n/2; i > 0; i--)
    {
        HeapAdjust(k, i, n);
    }
    for (int i = n; i > 1; i--)
    {
        swap(k, 1, i);
        HeapAdjust(k, 1, i-1);
    }
}
int main()
{
    int k[] = {-1, 2, 1, 5, 7, 5, 6, 10, 20, 15, 17, 16, 14, 13};
    HeapSort(k, 13);
    return 0;
}

将各步骤的运行结果列举如下:

  • 构建完大顶堆,数组为
20 17 14 15 16 13 10 7 1 5 2 6 5
  • 最大值与第i个值进行交换后构建新的大顶堆,数组分别为
i: 13
17 16 14 15 5 13 10 7 1 5 2 6 20 
i: 12
16 15 14 7 5 13 10 6 1 5 2 17 20 
i: 11
15 7 14 6 5 13 10 2 1 5 16 17 20 
i: 10
14 7 13 6 5 5 10 2 1 15 16 17 20 
i: 9
13 7 10 6 5 5 1 2 14 15 16 17 20 
i: 8
10 7 5 6 5 2 1 13 14 15 16 17 20 
i: 7
7 6 5 1 5 2 10 13 14 15 16 17 20 
i: 6
6 5 5 1 2 7 10 13 14 15 16 17 20 
i: 5
5 2 5 1 6 7 10 13 14 15 16 17 20 
i: 4
5 2 1 5 6 7 10 13 14 15 16 17 20 
i: 3
2 1 5 5 6 7 10 13 14 15 16 17 20 
i: 2
1 2 5 5 6 7 10 13 14 15 16 17 20 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值