学习堆排序

  首先,看一下堆的定义;

  n个元素的序列{k1,k2,…,kn}当且仅当满足下列关系之一时,称之为堆。

  情形1:k<= k2i 且k<= k2i+1 最小化堆小顶堆

  情形2:k>= k2i 且k>= k2i+1 (化堆大顶堆

  其中i=1,2,…,n/2向下取整;    

该排序的思想是;首先建立二叉堆,这个阶段花费O(N)时间,然后我们执行N次deleteMin操作。按照顺序,最小的元素先离开堆,通过将这些元素记录到第二数组,最后在将数组拷贝回来,得到N个元素的顺序,由于每个deleteMIn花费时间O(logN), 因此,总的运行时间是O(NlogN). 优先队列,可以用于O(NlogN)时间排序, 基于该思想的算法叫做堆排序。

该算法的主要问题是使用一个附加的数组,一次存储需求增加一倍,为了回避使用第二个数组的,可以在每次deleteMin之后,堆缩减1,因此,位于堆中左后的单元,可以存储刚刚存放删除的元素。使用这种策略,该数组将以递减的的顺序包含这些元素.

java代码的例子:

public class HeapSort {

    public static void main(String[] args) throws Exception{
        Integer [] a  = new Integer[]{32,12,345,5,66,23};
        heapSort(a);

        Arrays.stream(a).forEach(System.out::println);
    }

    /**
     * Internal method for heapSort that is used in  deleteMax and buiildHeap
     * @param i the position from which to percolate down
     * @param n the binary size of the binary heap
     */
    public static void percDown(Integer[] a,int i, int n){
        int child;
        int temp;

        for(temp= a[i]; leftChild(i) < n; i = child){
            child = leftChild(i);

            if(child != n-1  && a[child] < a[child+1])
                child++;

            if(temp < a[child])
                a[i] = a[child];
            else
                break;
        }
         a[i] = temp;
    }

    private static int leftChild(int i){
        return 2 * i + 1;
    }

    public static void heapSort(Integer[] a){

        /**初始化堆的时候是对所有的非叶子结点进行筛选。
        最后一个非终端元素的下标是[n/2]向下取整,所以筛选只需要从第[n/2]向下取整个元素开始,从后往前进行调整。
         */
        for(int i = a.length/2-1; i>=0; i--){ //buildHeap
            percDown(a,i,a.length);
        }

        for(int i=a.length-1; i > 0; i--){
            swapReferences(a,0,i);  //deleteMax
            percDown(a,0,i);
        }
    }

    //deleteMax
    public static void swapReferences(Integer[] a, int i, int n){
        Integer temp=a[i];
        a[i] = a[n];
        a[n] = temp;
    }

}

  堆排序方法对记录数较少的文件并不值得提倡,但对n较大的文件还是很有效的。因为其运行时间主要耗费在建初始堆和调整建新堆时进行的反复“筛选”上

  堆排序在最坏的情况下,其时间复杂度也为O(nlogn)。相对于快速排序来说,这是堆排序的最大优点。

   

 

  

    

时间: 2024-10-09 16:50:31

学习堆排序的相关文章

经典算法学习——堆排序

堆排序是相对其他排序稍微麻烦的排序,是一种利用堆的性质进行的选择排序.堆其实是一棵完全二叉树,只要任何一个非叶节点的关键字不大于或者不小于其左右孩子节点,就可以形成堆.堆分为大顶堆和小顶堆.由上述性质可知大顶堆的堆顶的关键字是所有关键字中最大的,小顶堆的堆顶的关键字是所有关键字中最小的.堆排序同快速排序一样都是不稳定排序.示例代码上传至:https://github.com/chenyufeng1991/HeapSort 堆排序的思想:利用大顶堆(小顶堆) 堆顶记录的是最大关键字(最小关键字)这

堆排序-学习笔记

在学习堆排序之前首先了解一下二叉堆的特性: 1.二叉堆的父节点的值总是大于等于(或小于等于)其左右孩子的值: 2.每个节点的左右子树都是一棵这样的二叉堆. 如果该二叉堆的父节点总是大于孩子节点,则叫做最大堆,如果父节点小于孩子节点,则叫做最小堆. 在堆排序的应用中,如果递增排序,则应该使用最大堆,反之,使用最小堆. 堆排序是不稳定的 堆排序主要有两个步骤来完成堆排序: 1.把一个无序数列构造成一个最大堆或最小堆: 2.去掉根节点(堆顶元素),把剩下的元素重新构造一个二叉堆. 二叉堆的存储结构为一

白话经典算法系列之七 堆与堆排序

堆排序与高速排序,归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法.学习堆排序前,先解说下什么是数据结构中的二叉堆. 二叉堆的定义 二叉堆是全然二叉树或者是近似全然二叉树. 二叉堆满足二个特性: 1.父结点的键值总是大于或等于(小于或等于)不论什么一个子节点的键值. 2.每一个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆). 当父结点的键值总是大于或等于不论什么一个子节点的键值时为最大堆.当父结点的键值总是小于或等于不论什么一个子节点的键值时为最小堆.下图展示一个最小堆

Java实现---堆排序 Heap Sort

堆排序与快速排序,归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法.学习堆排序前,先讲解下什么是数据结构中的二叉堆. 堆的定义 n个元素的序列{k1,k2,…,kn}当且仅当满足下列关系之一时,称之为堆. 情形1:ki <= k2i 且ki <= k2i+1 (最小化堆或小顶堆) 情形2:ki >= k2i 且ki >= k2i+1 (最大化堆或大顶堆) 其中i=1,2,…,n/2向下取整; 若将和此序列对应的一维数组(即以一维数组作此序列的存储结构)看成是一个完全

堆与堆排序

原文:http://blog.csdn.net/morewindows/article/details/6709644 堆排序与快速排序,归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法.学习堆排序前,先讲解下什么是数据结构中的二叉堆. 二叉堆的定义 二叉堆是完全二叉树或者是近似完全二叉树. 二叉堆满足二个特性: 1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值. 2.每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆). 当父结点的键值总是大于或等于任何

java实现算法之堆排序

本文参考文章:http://blog.csdn.net/morewindows/article/details/6709644 堆排序与快速排序,归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法.学习堆排序前,先讲解下什么是数据结构中的二叉堆. 二叉堆的定义 二叉堆是完全二叉树或者是近似完全二叉树. 二叉堆满足二个特性: 1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值. 2.每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆). 当父结点的键值总是大于或

白话经典算法系列之七 堆与堆排序(转)

堆排序与快速排序,归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法.学习堆排序前,先讲解下什么是数据结构中的二叉堆. 二叉堆的定义 二叉堆是完全二叉树或者是近似完全二叉树. 二叉堆满足二个特性: 1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值. 2.每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆). 当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆.当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆.下图展示一个最小堆: 由于其它几

堆排序详解

堆排序与快速排序,归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法.学习堆排序前,先讲解下什么是数据结构中的二叉堆. 二叉堆的定义 二叉堆是完全二叉树或者是近似完全二叉树. 二叉堆满足二个特性: 1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值. 2.每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆). 当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆.当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆.下图展示一个最小堆: 由于其它几

【转】白话经典算法系列之七 堆与堆排序

堆排序与快速排序,归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法.学习堆排序前,先讲解下什么是数据结构中的二叉堆. 二叉堆的定义 二叉堆是完全二叉树或者是近似完全二叉树. 二叉堆满足二个特性: 1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值. 2.每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆). 当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆.当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆.下图展示一个最小堆: 由于其它几