堆排序

作者: nlpming | 来源:发表于2020-06-25 22:49 被阅读0次
堆的定义
  • 堆是具有以下性质的 完全二叉树
    (1)每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;
    (2)每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆;
大顶堆与小顶堆.png
堆的底层实现
  • 堆使用一个一维数组表示;对堆中的元素进行编号,存入一维数组,如下图所示:
一维数组表示堆.png
  • 对于性质(1)和(2)用数学表达式表示为:
    (1)大顶堆:arr[i] >= arr[2i+1], arr[i] >= arr[2i+2]
    (2)小顶堆:arr[i] <= arr[2i+1], arr[i] <= arr[2i+2]
堆排序
  • 堆排序时间复杂度:O(nlogn)
  • 堆排序基本思想: 将待排序序列构造成大顶堆,此时整个序列的最大值就在堆顶的根结点;将堆顶元素与末尾元素进行交换,此时末尾元素变成最大值;将剩余的n-1元素重新调整成大顶堆,如此循环下去,就得到一个从小到大排序的序列。
  • 堆的重要性质:
    (1)第i个结点的左孩子为2i+1,右孩子为2i+2
    (2)第i个结点的父结点为(i-1)/2
    (2)堆中最后一个非叶子结点(n-2)/2,即为堆中最后一个结点n-1的父结点;
堆排序代码实现
  1. 构造大顶堆,从最后一个非叶子结点 (n-2)/2 开始调整元素,直到第一个元素调整结束,此时大顶堆构造完成;
  2. 开始堆排序过程,参见上面的 [堆排序基本思想]
  • 注意:printVector需自己实现
#include <iostream>
#include <vector>
#include <algorithm>
#include "print.h"

using namespace std;

/**
 * 调整堆的过程,从第i个结点开始调整堆
 * @param nums
 * @param i
 * @param n
 */
void adjustHeap(vector<int>& nums, int i, int n){
    if(i >= n)
        return;

    int maxIdx = i;
    int left = 2*i+1, right = 2*i+2;

    if(left < n && nums[left] > nums[maxIdx])
        maxIdx = left;
    if(right < n && nums[right] > nums[maxIdx])
        maxIdx = right;

    if(maxIdx != i){
        swap(nums[maxIdx], nums[i]);
        adjustHeap(nums, maxIdx, n);
    }
}

/**
 * 生成大顶堆,从最后一个非叶子结点开始调整
 * @param nums
 */
void makeHeap(vector<int>& nums){
    int n = nums.size();
    for(int i = (n-2)/2; i >= 0; i--){
        adjustHeap(nums, i, n);
    }
}

/**
 * 堆排序
 * @param nums
 * @return
 */
void heapSort(vector<int>& nums){
    int n = nums.size();
    for(int i = n-1; i >= 0; i--){
        swap(nums[i], nums[0]);
        adjustHeap(nums, 0, i); // 长度在缩小
    }
}


int main(){
    vector<int> nums = {1,6,5,3,2,8,9};

    // 构造大顶堆
    printVector(nums);
    makeHeap(nums);
    printVector(nums);

    // 堆排序
    heapSort(nums);
    printVector(nums);

    return 0;
}

参考资料

相关文章

  • 堆排序

    目录 1.堆排序介绍 2.堆排序图文说明 3.堆排序的时间复杂度和稳定性 4.堆排序实现 堆排序介绍 堆排序(He...

  • 堆排序---基础篇

    本文主要介绍堆排序的一些基本过程和分析。 大纲 堆排序简介 堆排序代码实现 1. 堆排序简介 1.1 堆排序的存储...

  • 堆和堆排序

    最小K个数 堆排序 堆排序

  • JS实现堆排序

    原理 堆排序原理 实现 说明 堆排序对大文件很有效 堆排序是不稳定排序

  • iOS算法总结-堆排序

    iOS算法总结-堆排序 iOS算法总结-堆排序

  • 堆排序

    转载:图解排序算法(三)之堆排序 预备知识 堆排序 堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选...

  • 排序

    原创 堆排序: 使用visit数组从本质出发获取大顶堆排序。

  • 堆排序

    堆排序

  • C++基础入门之模板堆排序(上):模板上的list的创造与操作

    整段源码链接C++的模板元堆排序 要点 组建数据结构list 组建对list的各种基本操作 堆排序中组建堆排序个个...

  • 3.2-选择排序-堆排序

    参考链接 选择排序:堆排序(Heap Sort) 白话经典算法系列之七 堆与堆排序 堆排序与快速排序,归并排序一样...

网友评论

      本文标题:堆排序

      本文链接:https://www.haomeiwen.com/subject/kqyefktx.html