zoukankan      html  css  js  c++  java
  • 知道堆排序吗?

    堆排序介绍

      堆排序是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。

      堆是一个近完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

    什么是完全二叉树呢?还有满二叉树又是怎么的一种二叉树呢?还有完满二叉树?

    • 完全二叉树: 除了最后一层之外的其他每一层都被完全填充,并且所有结点都保持向左对齐
    • 满二叉树:除了叶子结点之外的每一个结点都有两个孩子,每一层(当然包含最后一层)都被完全填充。
    • 完满二叉树:除了叶子结点之外的每一个结点都有两个孩子结点。

    下面用图来说话:

    • 完全二叉树(Complete Binary Tree):

    • 满二叉树(Perfect Binary Tree):

    • 完满二叉树(Full Binary Tree):

    简单来说:

      堆排序是将数据看成是完全二叉树、根据完全二叉树的特性来进行排序的一种算法

      最大堆要求节点的元素都要不小于其孩子,最小堆要求节点元素都不大于其左右孩子

      那么处于最大堆的根节点的元素一定是这个堆中的最大值

    完全二叉树有个特性:

      左边子节点位置 = 当前父节点的两倍 + 1右边子节点位置 = 当前父节点的两倍 + 2

    堆排序代码实现 :

     1 /**
     2      * 建堆
     3      *
     4      * @param arrays          看作是完全二叉树
     5      * @param currentRootNode 当前父节点位置
     6      * @param size            节点总数
     7      */
     8     public static void heapify(int[] arrays, int currentRootNode, int size) {
     9 
    10         if (currentRootNode < size) {
    11             //左子树和右字数的位置
    12             int left = 2 * currentRootNode + 1;
    13             int right = 2 * currentRootNode + 2;
    14 
    15             //把当前父节点位置看成是最大的
    16             int max = currentRootNode;
    17 
    18             if (left < size) {
    19                 //如果比当前根元素要大,记录它的位置
    20                 if (arrays[max] < arrays[left]) {
    21                     max = left;
    22                 }
    23             }
    24             if (right < size) {
    25                 //如果比当前根元素要大,记录它的位置
    26                 if (arrays[max] < arrays[right]) {
    27                     max = right;
    28                 }
    29             }
    30             //如果最大的不是根元素位置,那么就交换
    31             if (max != currentRootNode) {
    32                 int temp = arrays[max];
    33                 arrays[max] = arrays[currentRootNode];
    34                 arrays[currentRootNode] = temp;
    35 
    36                 //继续比较,直到完成一次建堆
    37                 heapify(arrays, max, size);
    38             }
    39         }
    40     }

    值得注意的是:

      在上面体验堆排序时,我们是左子树和右子数都是已经有父>子这么一个条件的了。

      显然,一个普通的数组并不能有这种条件(父>子),因此,我们往往是从数组最后一个元素来进行建堆

     1     /**
     2      * 完成一次建堆,最大值在堆的顶部(根节点)
     3      */
     4     public static void maxHeapify(int[] arrays, int size) {
     5 
     6         // 从数组的尾部开始,直到第一个元素(角标为0)
     7         for (int i = size - 1; i >= 0; i--) {
     8             heapify(arrays, i, size);
     9         }
    10 
    11     }

    接下来不断建堆,然后让数组最后一位与当前堆顶(数组第一位)进行交换即可排序:

     1     for (int i = 0; i < arrays.length; i++) {
     2 
     3         //每次建堆就可以排除一个元素了
     4         maxHeapify(arrays, arrays.length - i);
     5 
     6         //交换
     7         int temp = arrays[0];
     8         arrays[0] = arrays[(arrays.length - 1) - i];
     9         arrays[(arrays.length - 1) - i] = temp;
    10 
    11     }
  • 相关阅读:
    hdu 4825 Xor Sum(01字典树模版题)
    poj 2778 DNA Sequence(ac自动机+矩阵快速幂)
    codeforces 626 G. Raffles(线段树+思维+贪心)
    hdu 2615 Division(暴力)
    hdu 6092 Rikka with Subset(多重背包)
    codeforces 688 E. The Values You Can Make(01背包+思维)
    JavaUtil smtp 邮件发送
    JavaUtil 处理Base64的图片上传
    Centos7 在apache+php7环境下 安装 Discuz!X3.4
    Centos7 安装 apache + php7.0 环境
  • 原文地址:https://www.cnblogs.com/yslf/p/11145867.html
Copyright © 2011-2022 走看看