堆排序heapSort

堆排序——排序算法笔记

1. 二叉堆

二叉堆是完全二叉树或者是近似完全二叉树

二叉树特性:

  1. 父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。
  2. 每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。
(1)大堆

父结点的键值总是大于或等于任何一个子节点的键值

(2) 小堆

父结点的键值总是小于或等于任何一个子节点的键值

2. 堆的存储

堆的逻辑结构是树,但是一般存储的方式是数组;

逻辑结构:

image.png

存储结构:
image.png

i 结点的父结点:(i - 1) / 2;

i 结点的左子节点:i * 2 + 1;

i 结点的右子节点:i * 2 + 2

基本思路

  1. 将给定无序序列构造成一个大顶堆(一般升序采用大顶堆,降序采用小顶堆)。
    image.png

    第一个非叶子节点 1(arr[i] = 6)的计算:

方法一:

最末子结点 = length - 1;

最末子结点的父结点 = (最末子节点 - 1)/ 2

方法二:

length / 2 - 1


image.png
  1. 找到第二个非叶节点4,由于[4,9,8]中9元素最大,4和9交换


    image.png
  2. 将[图片上传中...(image.png-af7acd-1582374158730-0)]
    堆顶元素9和末尾元素4进行交换。


    image.png
  3. 重新调整结构,使其继续满足堆定义


    image.png
  4. 再将堆顶元素8与末尾元素5进行交换,得到第二大元素8.


    image.png

    ​ 实现这一步方式,直接将arr的length-1,长度递减

    for(int i = lens - 1; i >= 0; i--){
        swap(arr[0], arr[i]);
        heapify(arr, i, 0);
    }

问题:heapify只能完成一个节点的heapify

所以堆排中很重要的一点的是:


image.png
void buildHeap(int *arr, int lens)
{   
    //计算最底层的“第一个”父结点
    int last_node = lens - 1;
    int parent_node = (last_node - 1) / 2;
    
    //从底层开始向上回溯
    for(int i = parent_node; i >= 0; i--){
        heapify(arr, lens, i);
    }
}

参考链接:https://www.bilibili.com/video/av47196993?from=search&seid=5468598825988489537

递归方法的堆排序:

#include <iostream>
#include <string.h>
#include <vector>
using namespace std;

void heapify(vector<int>& nums, int lens, int index)
{
    if (index > lens)
    {
        return;
    }
    
    int left = index * 2 + 1;

    if (left < lens)
    {
        int maxIndex = left + 1 < lens && nums[left + 1] > nums[left]? left + 1 : left;
        maxIndex = nums[maxIndex] > nums[index]? maxIndex : index;
        if (maxIndex != index)
        {
            swap(nums[maxIndex], nums[index]);
            heapify(nums, lens, maxIndex);
        }        
    }
}

void heapSort(vector<int>& nums)
{
    int lens = nums.size();
    for (int i = lens / 2 - 1; i >= 0 ; i--)
    {
        heapify(nums, lens, i);
    }

    for (int i = lens - 1; i > 0 ; i--)
    {   
        swap(nums[0], nums[i]);
        heapify(nums, i, 0);
    }
}

int main()
{
    int arr[5] =  {5,4,3,2,1};
    vector<int> nums;
    for (int i = 0; i < 5; i++)
    {
        nums.push_back(arr[i]);
    }
    heapSort(nums);
    for (int i = 0; i < 5; i++)
    {
        printf("%d",nums[i]);
    }
    
    return 0;
}

推荐阅读更多精彩内容