• 排序算法 -- 堆排序


    前言

    面试中被问到了一个题目(http://www.voidcn.com/blog/u010943214/article/p-3808842.html),然后重温了一遍堆排序。

    问题:

    给你一个双向链表,有序输出,

    限制:

      空间复杂度O1,

      时间复杂度nlogn,最坏不能退化n2

    思路:

      1 根据双向链表构建一个二叉树

      2 对二叉树进行堆排序

    堆的定义

      定义:堆如果用一个二叉树表示的话,那应该是具有以下特性的二叉树

        a 树的形状要求 -- 这颗二叉树是基本完备的(或者简称完全二叉树),这意味着树的每一层都是满的,最后一层最右边的孩子节点有可能空缺

        b 父母优势要求 -- 键的要求 ,父母的键必须大于等于所有子树节点(对于任何叶子节点认为是自动满足的)

    堆的特性

    1 树的根总是包含了最大元素

    2 分形特性, 堆的一个节点以及该节点的子孙也是一个堆

    3 可以用数组实现一个堆,方法是从上到下,从左到右记录堆的元素,从1...n的位置记录n个元素,在这种表示法中,

      a 父母节点的键将位于前 n/2的位置上,叶子节点占据后 n/2个位置

      b 对于一个位于位置i的节点, 它的子女将会位于2i 和 2i+1上,对于一个位于位置i的键来说,它的子女将会位于i/2上。

    如何构造一个堆

    构造堆的过程叫做堆化,这个过程的输入是一个无序数组,输出是一个满足堆特性的数组。

    这个过程是从最后一个父母开始,直到堆根为止,检查这个节点是否满足堆的父母优势,如果不满足,交换父母和其中一个子女节点,在新的子女节点位置上,同样检查父母优势,直到满足了父母优势 或者 节点到达了叶子节点

    上树过程有两个直到,就是两个循环。

    堆化的算法如下

    void HeapfyBottomeUp(int a[], int len)
    
    {
    
      forint i = len/2; i >= 1; i--)
    
      {
    
        int k = i;
        int temp = a[i];
        bool isHeap = false;
        while(!isHeap && 2*k<=len)
        {
          int j = 2*k;
          if( j+1 <= len && H[j] < H[j+1])
            j++;
          if(temp >= H[j])
            isHeap = true;
          else
          {
            H[k] = H[j];
            k = j;
          }
        }
        H[k] = temp ;
      }
    
    }

    构造一个堆的时间复杂度

      堆化可以在O(n)时间复杂度内完成。

      具体思路如下,第i层有2的i次个元素(i从0计数), 那最坏情况下,第i层需要对比2(h-i)次,每一个对比都要从当前位置到叶子节点, h 是数的深度。

      具体推导如下: 

        

    如何从堆中删除最大的键值

      1 把堆根和最后一个叶子节点交换

      2 堆的数量-1

      3 剩余的堆进行堆化的过程。

    时间复杂度 O(logn)

    堆排序

      再来介绍堆排序就简单了

      堆排序本质上是说,不断的对堆根实施删除,堆化的过程,直到堆的大小变成1 停止,时间复杂度是 O(nlogn)

      算法:

        1 构造一个规模是n的堆

        2 对这个堆 执行 n-1 次 堆根删除操作。

    时间复杂度对比

      和 合并排序(归并排序)有同样的时间复杂度,堆排序是在位的,不需要额外的空间, 针对随机文件的计时试验指出(无参考,可以自行对比),堆排序比快排运行的慢,但是和 合并排序有竞争力。

    堆排序使用场景

     面试题  笔试题。。。。

  • 相关阅读:
    Things You Should Know
    因为web.config配置,导致(当前不会命中断点,还没有为该文档加载任何符号)
    【HTML5 Canvas游戏开发】笔记(二) 显示一张图片
    【HTML5 Canvas游戏开发】笔记(一) 概述和基础讲解
    const char* pcr&char* const pcr
    【Python扩展阅读【转】EasyGui 学习文档【超详细中文版】】
    【Python扩展阅读【转】】字符串的方法及注释
    【Python⑥】python的缩进,条件判断和循环
    【Python⑤】python序列---list和tuple
    【Python④】python恼人的字符串,格式化输出
  • 原文地址:https://www.cnblogs.com/bianzeming/p/6538638.html
Copyright © 2020-2023  润新知