c++实现堆排序

16 篇文章 0 订阅
16 篇文章 0 订阅

代码说明

代码是我亲自码的,调试通过的,代码中有算法思想和详细的注释,一目了然。

项目已经上传到我的github:https://github.com/yisun03/sort

项目中还有另外得九种排序算法的c++实现代码以及其思想。

十种排序算法清代如下(附我的blog链接):

1   选择排序:https://blog.csdn.net/weixin_39408343/article/details/107063290              
2   插入排序:https://blog.csdn.net/weixin_39408343/article/details/107070155                   
3   冒泡排序:https://blog.csdn.net/weixin_39408343/article/details/107070658              
4   希尔排序:https://blog.csdn.net/weixin_39408343/article/details/107071758
5.1 归并排序递归实现:https://blog.csdn.net/weixin_39408343/article/details/107083607
5.2 归并排序非递归实现:https://blog.csdn.net/weixin_39408343/article/details/107084688
6.1 快速排序递归实现:https://blog.csdn.net/weixin_39408343/article/details/107086104
6.2 快速排序非递归实现:https://blog.csdn.net/weixin_39408343/article/details/107087359
7   堆排序:https://blog.csdn.net/weixin_39408343/article/details/107092851
8   计数排序:https://blog.csdn.net/weixin_39408343/article/details/107094547
9   桶排序:https://blog.csdn.net/weixin_39408343/article/details/107113821
10  基数排序:https://blog.csdn.net/weixin_39408343/article/details/107115403

术语说明

1、稳定排序:如果 a 原本在 b 的前面,且 a == b,排序之后 a 仍然在 b 的前面,则为稳定排序。

2、非稳定排序:如果 a 原本在 b 的前面,且 a == b,排序之后 a 可能不在 b 的前面,则为非稳定排序。

3、原地排序:原地排序指在排序过程中不申请多余的存储空间,只利用原来存储待排数据的存储空间进行比较和交换的数据排序。

4、非原地排序:需要利用额外的数组来辅助排序。

5、时间复杂度:一个算法执行所消耗的时间。

6、空间复杂度:运行完一个算法所需的内存大小。

性能分析

时间复杂度:O(n*log(n))

空间复杂度:O(1)

非稳定的原地排序
 

 void sort::sort_heap(std::vector<int> &data)
  {
    // 思想:
    // 在原始序列上直接操作.
    // 利用二叉堆的数据结构来实现排序,二叉堆是一个完全二叉数.
    // 二叉堆的特点是堆顶元素是一个最值(大顶堆的堆顶为最大值,小顶堆的堆顶为最小值);
    // 大顶堆:任意节点的元素都要大于他的子节点元素,小顶堆:任意节点的元素都要小于他的子节点元素.
    // 排序方法是将堆顶元素和最后一个元素交换,然后恢复大/小顶堆;再将堆顶元素和最后第二个元素交换,以此类推.
    // 排序第一步是需要将原始数据构建乘二叉堆(升序排序构建大顶堆,降序排序构建小顶堆),我们升序排序所以构建大顶堆;
    // 第二步是调整使之重新成为大顶堆,我们使用从最后一个非叶子节点往上进行下沉处理(down_adjust()).
    // 此处我们提供了二叉堆的插入元素后维护二叉堆的操作,采用上浮处理(up_adjust).

    // 建堆:从最后一个非叶子节点往上做下沉操作.
    int length = data.size();
    // 思考为什么是减2.
    for(int i = (length - 2)/2; i >= 0; i--)
    {
      down_adjust(data,i,length -1);
    }
    // 开始堆排序
    for(int i = length -1; i > 0; i--)
    {
      // 将堆顶节点与节点i交换.
      int temp = data.at(0);
      data.at(0) = data.at(i);
      data.at(i) = temp;
      // 恢复二叉堆.
      down_adjust(data,0,i - 1);
    }
  }

  void sort::down_adjust(std::vector<int> &data, int parent, int length)
  {
    // 对parent节点做下沉操作.
    // 临时保存要下沉的节点.
    int key = data.at(parent);
    // 定位左子节点.
    int child = 2 * parent + 1;
    while(child <= length)
    {
      // 定位parent的较大的子节点.
      if(child + 1 <= length && data.at(child) < data.at(child + 1))
      {
        ++child;
      }
      // 如果parent节点的元素大于子节点的元素,则下沉完成.
      if(key >= data.at(child))
      {
        // 注意此处是break而不是return(想想为什么).
        break;
      }
      // 需要下沉,将child节点放到父节点.
      data.at(parent) = data.at(child);
      // 更新parent和child,以便继续下沉操作.
      parent = child;
      child = 2 * parent +1;
    }
    // 找到下沉位置后将下沉元素放到正确位置上后完成操作.
    data.at(parent) = key;
  }

  void sort::up_adjust(std::vector<int> &data, int length)
  {
    // 将末节点上浮到适当位置.
    // 定位父子节点.
    int child = length - 1;
    int parent = (child - 1)/2;
    // 临时保存需要上浮的节点.
    int key = data.at(child);
    // 开始上浮(大顶堆)
    while(child > 0 && key > data.at(parent))
    {
      // 如果要上浮的节点元素大于父节点,则将parent节点放到其子节点上.
      data.at(child) = data.at(parent);
      // 更新parent和child,以继续上浮操作.
      child = parent;
      parent = (child - 1)/2;
    }
    // 找到上浮位置后,将要上浮的节点放进去.
    data.at(child) = key;
  }

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

yisun03

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

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

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

打赏作者

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

抵扣说明:

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

余额充值