HeapSort堆排序C++实现及相关背景知识

堆排序的平均时间复杂度为 O(nlogn) ,空间复杂度为 Θ(1)

目录

堆排序HeapSort

算法流程

首先进行大顶堆的初始化,然后迭代地执行“把最大堆堆顶元素取出,与待排序数组末端元素交换;堆中元素个数减一,将剩余的堆继续调整为最大堆”的过程,直到堆中只剩一个元素,算法结束。

Cpp实现

//最大堆调整:将堆的末端子节点作调整,使得子节点永远小于父节点
void max_heapify(int* arr, int beg, int end){
    int dad = beg, son = 2 * dad + 1;
    while (son <= end){
        if (son + 1 <= end && arr[son] < arr[son + 1]) ++son;
        if (arr[dad] > arr[son]) return;
        swap(arr[dad], arr[son]);
        dad = son;
        son = 2 * dad + 1;
    }
}

void heap_sort(int* arr, int len){
    if (!arr || len<2) return;
    //大顶堆的初始化,从最后一个父节点开始调整
    for (int i = len / 2 - 1; i >= 0; --i) max_heapify(arr, i, len-1);
    for (int i = len-1; i > 0; --i){
        swap(arr[0], arr[i]);//把最大堆堆顶元素取出,与待排序数组末端元素交换
        max_heapify(arr, 0, i-1);//堆中元素个数减一,将剩余的堆继续调整为最大堆
    }
}

reference:wiki


背景知识

二叉树

常被用于实现二叉查找树和二叉堆。

对任意树,

  • 节点的度定义为该节点的分叉数(子女数)
  • 树中节点数 = 总分叉数+1

对任意二叉树,

  • 子树有左右之分
  • i 层至多2i1个节点
  • 深度为 k 的树至多2k1个节点
  • 度为 0 的节点个数 = 度为 2 的节点个数+1
完全二叉树
除了最下一层外,其它各层的节点数目均已达最大值,且最下一层所有节点从左向右连续地紧密排列。
满二叉树
所有叶节点都在最底层的完全二叉树
平衡二叉树(AVL树)
当且仅当任何节点的两棵子树的高度差不大于1的二叉树
二叉搜索树(Binary Search Tree)
是指一棵空树或者具有下列性质的二叉树:
    若节点x左子树不空,则左子树上所有节点的值均小于x的值;
    若节点x右子树不空,则右子树上所有节点的值均大于x的值;
    任意节点的左、右子树也分别为二叉查找树。

堆(Heap)

当且仅当n个元素满足下列关系时称之为堆:

k1,k2...ki...kn(ki<=k2i,ki<=k2i+1);(ki>=k2i,ki>=k2i+1)

即子结点的键值或索引总是小于(或大于)它的父节点。(其中,i = 1,2,3,4…n/2)

堆是一个近似完全二叉树的结构。
完全二叉树的一个“优秀”的性质是,除了最底层之外,每一层都是满的,这使得堆可以利用数组来表示(普通的一般的二叉树通常用链表作为基本容器表示),每一个结点对应数组中的一个元素。如下图所示:
堆和数组的对应关系
img reference:blog

注意:数组都是 Zero-Based的。

对于给定的某个结点在数组中的下标 i,可以很容易的计算出该结点的父结点、孩子结点的下标:

  • i 的父节点下标 Parent(i)=floor((i1)/2)
  • i 的左孩子节点下标 Left(i)=2i+1
  • i 的右孩子节点下标 Right(i)=2i+2

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值