【c++】堆排序

  1. 建堆【以大顶堆为例】

image.png

  1. 排序

image.png

性能

  1. 建堆的时间复杂度为O(N)
  2. heapify复杂度O(logN)
  3. 堆排序对N个数进行heapify

堆排序的时间复杂度:O(NlogN)

为何堆排序是不稳定排序?

当数组中有相等元素时,堆排序算法对这些元素的处理方法不止一种,故是不稳定的。

实现

//heapSort.cc
#include "heapSort.h"

void heapify(vector<int>& nums, int pos, int len) {
    int parent = pos;
    int son = 2 * pos + 1;  //son表示挑战的孩子的下标
    //2N+1是左子节点的下标
    while(son < len) {   
        if(son + 1 < len && nums[son] < nums[son + 1]) {
            //右结点存在,且强于左节点
            //先和兄弟比
            son = son + 1;
        }   
        if(nums[son] > nums[parent]) {
            //在和父亲比
            std::swap(nums[son], nums[parent]);
            //父亲被替换到新的位置,向下继续循环
            parent = son;                                              
            son = 2 * parent + 1;
        }   
        else {
            //如果不交换,循环终止
            break;
        }             
    }   
}

void heap_sort(vector<int>& nums) {
    //建堆
    //最后一个父结点下标是N/2-1
    for(int i = nums.size() / 2 - 1; i >= 0; i--) {
        //i表示起点的下标,从最后一个父结点到根节点
        heapify(nums, i, nums.size());
    }   
    std::swap(nums[0], nums[nums.size() - 1]);
    //交换根节点(最大值)和最后一个结点的位置,并把堆大小减1
    //排序
    for(int len = nums.size() - 1; len > 0; len--) {
        //i表示堆的规模
        heapify(nums, 0, len);
        std::swap(nums[0], nums[len - 1]);
    }
}
//heapSort.h
#ifndef __HEAP_SORT_H_
#define __HEAP_SORT_H_
#include <vector>
#include <algorithm>                                                   
using std::vector;

//大根法的树
//满足两个性质:
//1. 满足完全二叉树
//2. 父结点比子结点大,根结点最大
//pos指向子树调整的起点的下标,起点编号是pos+1
//左孩子下标2*pos+1,编号2*pos+2
//右孩子下标2*pos+2,编号2*pos+3
//堆最后一个元素的编号len,  下标len-1
//
void heapify(vector<int>& nums, int pos, int len);
void heap_sort(vector<int>& nums);

#endif //end of __HEAP_SORT_H__

//main.cc
#include <iostream>
#include "selectSort.h"
#include <cstdlib>
#include <ctime>
#include "heapSort.h"
using std::cout;
using std::endl;

const size_t nums_len = 10; 

void print(vector<int>& nums) {
    for(auto i : nums) {
        cout << i << ' ';
    }   
    cout << endl;
}

void test() {
    //创建测试数据
    std::srand(std::time(nullptr));
    vector<int> nums;
    for(int i = 0; i < nums_len; ++i) {
        nums.push_back(std::rand() % 99);
    }   
    
    print(nums);
    //select_sort(nums);
    heap_sort(nums);
    print(nums);
}

int main(void)
{
    test();
}

swap函数的使用
Before C++11, this function was defined in header .

// swap algorithm example (C++11)
#include <iostream>     // std::cout
#include <utility>      // std::swap

int main () {

  int x=10, y=20;                  // x:10 y:20
  std::swap(x,y);                  // x:20 y:10

  int foo[4];                      // foo: ?  ?  ?  ?
  int bar[] = {10,20,30,40};       // foo: ?  ?  ?  ?    bar: 10 20 30 40
  std::swap(foo,bar);              // foo: 10 20 30 40   bar: ?  ?  ?  ?

  std::cout << "foo contains:";
  for (int i: foo) std::cout << ' ' << i;
  std::cout << '\n';

  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值