zoukankan      html  css  js  c++  java
  • 排序算法 -- 堆排序

    前言

    面试中被问到了一个题目(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 次 堆根删除操作。

    时间复杂度对比

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

    堆排序使用场景

     面试题  笔试题。。。。

  • 相关阅读:
    iScroll.js 用法参考
    行内元素和块级元素
    struct和typedef struct彻底明白了
    C/C++语法知识:typedef struct 用法详解
    不是技术牛人,如何拿到国内IT巨头的Offer (转载)
    笔试客观题-----每天收集一点点
    <C++Primer>第四版 阅读笔记 第一部分 “基本语言”
    <C++Primer>第四版 阅读笔记 第四部分 “面向对象编程与泛型编程”
    <C++Primer>第四版 阅读笔记 第三部分 “类和数据抽象”
    <C++Primer>第四版 阅读笔记 第二部分 “容器和算法”
  • 原文地址:https://www.cnblogs.com/bianzeming/p/6538638.html
Copyright © 2011-2022 走看看