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

来源:互联网 发布:加内特08年总决赛数据 编辑:程序博客网 时间:2024/06/05 10:30

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

目录

    • 堆排序HeapSort
      • 算法流程
      • Cpp实现
    • 背景知识
      • 二叉树
        • 完全二叉树
        • 满二叉树
        • 平衡二叉树AVL树
        • 二叉搜索树Binary Search Tree
      • 堆Heap

堆排序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

原创粉丝点击