算法三之堆排序

一、堆(Heap)定义

(1)n个关键字序列Kl,K2,…,Kn称为(Heap),当且仅当该序列满足如下性质(简称为堆性质):

k(i)<=k(2i)且k(i)<=k(2i+1)(1≤i≤ n/2),

当然,这是小根堆,大根堆则换成>=号。

(2)k(i)相当于二叉树的非叶子结点,K(2i)则是左子节点,k(2i+1)是右子节点

若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:
树中任一非叶子结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。

二、堆排序的思想

堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。

(1)用大根堆排序的基本思想

① 先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区

② 再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key

③由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。

……

直到无序区只有一个元素为止。

三、算法实现

    /**
     * 堆排序
     * @param data  数据队列
     */
    public static void heapSort(int[] data) {
        //初始化大堆
        for (int i = data.length / 2 - 1; i >= 0; i--) {
            adjustHeap(data, i, data.length);  //指定父节点堆调整
        }

        int temp;    //临时空间
        for (int i = data.length - 1; i > 0; i--) {
            //堆首与堆尾交换
            temp = data[i];
            data[i] = data[0];
            data[0] = temp;
            //大堆调整
            adjustHeap(data, 0, i);
        }

    }
    /**
     * 堆调整
     * @param data  数据队列
     * @param start  起始位置
     * @param end   截止位置,是堆尾的下一个位置
     */
    public static void adjustHeap(int[] data, int start, int end) {

        int src=data[start];  //保存起始位置的值
        for (int i = start * 2 + 1; i < end; i *= 2 + 1) {
            //判断左右节点大小
            if (i < end - 1 && data[i] < data[i + 1]) {
                i++;  //右节点大
            }
            //起始位置值最大
            if(data[start]>data[i])
                break;

            data[start]=data[i];//赋值最大值
            start=i; //记录大值的位置
        }
        data[start]=src;//回填大值位置
    }

四、算法复杂度

堆排序的时间,主要由建立初始堆和反复重建堆这两部分的时间开销构成,它们均是通过调用adjustHeap实现的。

平均性能O(N*logN),由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件。

堆排序是就地排序,辅助空间为O(1).

它是不稳定的排序方法。(排序的稳定性是指如果在排序的序列中,存在前后相同的两个元素的话,排序前 和排序后他们的相对位置不发生变化)

时间: 2024-10-24 11:07:07

算法三之堆排序的相关文章

(高效率排序算法三)堆排序

一.堆的介绍         动态效果图         堆有如下特点的二叉树: 1.他是完全的二叉树.也就是说,除了树的最后一层布需要时满的,其他的每一层从左到右都是满的.(如下图的完全二叉树跟不完全二叉树) 2.它常常用一个数组在实现.(如下图显示了堆它与数组之间的关系.堆在存储器中的表示是数组:堆只是概念上的表示.注意树是完全二叉树,并且所有的节点满足堆的条件) 3.堆中的每一个节点都满足堆的条件,也就是说每一个节点的值都大于或者等于这个节点的子节点的值(如上图) 二,堆的移除 1.只能移

排序算法三:堆排序(Heapsort)

堆排序(Heapsort)是一种利用数据结构中的堆进行排序的算法,分为构建初始堆,减小堆的元素个数,调整堆共3步. (一)算法实现 1 protected void sort(int[] toSort) { 2 buildHeap(toSort); 3 for (int i = toSort.length - 1; i > 0; i--) { 4 CommonUtils.swap(toSort, 0, i); 5 adjustHeap(toSort, 0, i); 6 } 7 } 8 9 /**

排序算法(三)之堆排序

预备知识 堆排序 堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序.首先简单了解下堆结构. 堆 堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆:或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆.如下图: 同时,我们对堆中的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子 该数组从逻辑上讲就是一个堆结构,我们用简单的公式来描述一下堆的定义就是: 大顶

排序算法(三)堆排序及有界堆排序Java实现及分析

1.堆排序基数排序适用于大小有界的东西,除了他之外,还有一种你可能遇到的其它专用排序算法:有界堆排序.如果你在处理非常大的数据集,你想要得到前 10 个或者前k个元素,其中k远小于n,它是很有用的. 例如,假设你正在监视一 个Web 服务,它每天处理十亿次事务.在每一天结束时,你要汇报最大的k个事务(或最慢的,或者其它最 xx 的).一个选项是存储所有事务,在一天结束时对它们进行排序,然后选择最大的k个.需要的时间与nlogn成正比,这非常慢,因为我们可能无法将十亿次交易记录在单个程序的内存中.

算法笔记之堆排序

一.对堆排序的相关了解 1.堆排序的运行时间是 O(nlogn) : 2.定义: 堆heap是一棵具有以下属性的二叉树-- (1)它是一棵完全二叉树: (2)每个结点大于或等于它的任意一个孩子. 备注:完全二叉树的定义--除了最后一层没填满以及最后一层的叶子都是偏左放置的,其他层都是满的二叉树! 3.二叉堆有两种:最大堆和最小堆.在堆排序中我们使用的是最大堆,最小堆常常在构造优先队列时使用. 4.一条路径的深度指的是这条路径的边数,一个结点的深度是指从根结点到该结点的路径的长度. 二.对堆进行排

排序算法总结之堆排序

一,堆排序介绍 堆是一个优先级队列,对于大顶堆而言,堆顶元素的权值最大.将 待排序的数组 建堆,然后不断地删除堆顶元素,就实现了排序.关于堆,参考:数据结构--堆的实现之深入分析 下面的堆排序算法将数组中的元素从小到大排序,用大顶堆来实现. 二,堆排序算法分析 现给定了一维数组,需要将数组中的元素使用堆排序.首先,得创建一个堆,可以在这个给定的一维数组上建堆. 对N个元素 建堆的时间复杂度为O(N) 堆排序具体的细节实现有两种方式:一种方式是将堆顶元素删除后,放到一个辅助数组中,然后进行堆调整使

白话经典算法二叉堆排序之思想简介

常用的排序算法有冒泡排序,插入排序和选择排序.他们的时间复杂度是o(n2),与数据量的平方成正比.他们的效率还是比较低的.现在来说说他们的效率为什么比较低下.以冒泡排序为例,它每一轮都是与相邻的元素进行交换,交换的距离为1,每次每个(没有冒泡出来的)元素都要与前一个比较再交换.每次相邻的比较只能比较出两个元素的大小,不能以整个数组进行参照来确定在整个数组里的大小,也就是说每次的比较不能确定其他元素的相对位置,因而每次比较的贡献不大,所以这样的比较是笨拙的,进而需要完全比较O(n2)次才能得出正确

算法基础之五(堆排序)

堆排序,首先要了解一下这里的堆是什么,这里的堆其实就是二叉树,很形象是不是,完整的二叉树从头看起,就是一个三角形,也可以看成一个"堆". 一.数组转换成堆 那么首先要解决的问题就是给数组排序,如何转换成二叉树的?转换方法如图: 数组 int a[],包含元素a[0],a[1],a[2],a[3].....等等. 转换成二叉树: 图还是比较形象的,其实就是依次从堆顶向下排,但是有一个原则,就是上一层没有排满的时候,下一层不会有元素,有限排满上一层,才考虑下一层. 二.如何进行堆排序 那么

三、堆排序(Heapsort),优先队列可以用于O(N log N)

三.堆排序(Heapsort) 优先队列可以用于O(N log N) 存储空间增加一倍 排序类别 排序方法 时间复杂度 时间复 杂度 空间复杂度 稳定性 复杂性 平均情况 最坏情况 最好情况 选择排序 堆排序 O(nlog2n) O(nlog2n) O(nlog2n) O(1) 不稳定 较复杂 堆排序:堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序.首先简单了解下堆结构. 堆:堆是具有以下性质的完全二叉树