`
m635674608
  • 浏览: 5054460 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

堆排序原理及算法实现(最大堆)

 
阅读更多

堆排序

       堆排序是利用堆的性质进行的一种选择排序。下面先讨论一下堆。

1.堆

  堆实际上是一棵完全二叉树,其任何一非叶节点满足性质:

  Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]或者Key[i]>=Key[2i+1]&&key>=key[2i+2]

  即任何一非叶节点的关键字不大于或者不小于其左右孩子节点的关键字。

  堆分为大顶堆和小顶堆,满足Key[i]>=Key[2i+1]&&key>=key[2i+2]称为大顶堆,满足 Key[i]<=key[2i+1]&&Key[i]<=key[2i+2]称为小顶堆。由上述性质可知大顶堆的堆顶的关键 字肯定是所有关键字中最大的,小顶堆的堆顶的关键字是所有关键字中最小的。

2.堆排序的思想

   利用大顶堆(小顶堆)堆顶记录的是最大关键字(最小关键字)这一特性,使得每次从无序中选择最大记录(最小记录)变得简单。

    其基本思想为(大顶堆):

    1)将初始待排序关键字序列(R1,R2....Rn)构建成大顶堆,此堆为初始的无须区;

    2)将堆顶元素R[1]与最后一个元素R[n]交换,此时得到新的无序区(R1,R2,......Rn-1)和新的有序区(Rn),且满足R[1,2...n-1]<=R[n]; 

    3)由于交换后新的堆顶R[1]可能违反堆的性质,因此需要对当前无序区(R1,R2,......Rn-1)调整为新堆,然后再次将R[1]与无序区最 后一个元素交换,得到新的无序区(R1,R2....Rn-2)和新的有序区(Rn-1,Rn)。不断重复此过程直到有序区的元素个数为n-1,则整个排 序过程完成。

    操作过程如下:

     1)初始化堆:将R[1..n]构造为堆;

     2)将当前无序区的堆顶元素R[1]同该区间的最后一个记录交换,然后将新的无序区调整为新的堆。

    因此对于堆排序,最重要的两个操作就是构造初始堆和调整堆,其实构造初始堆事实上也是调整堆的过程,只不过构造初始堆是对所有的非叶节点都进行调整。

    下面举例说明:

     给定一个整形数组a[]={16,7,3,20,17,8},对其进行堆排序。

    首先根据该数组元素构建一个完全二叉树,得到

 
 然后需要构造初始堆,则从最后一个非叶节点开始调整,调整过程如下:

20和16交换后导致16不满足堆的性质,因此需重新调整

这样就得到了初始堆。

即每次调整都是从父节点、左孩子节点、右孩子节点三者中选择最大者跟父节点进行交换(交换之后可能造成被交换的孩子节点不满足堆的性质,因此每次交换之后要重新对被交换的孩子节点进行调整)。有了初始堆之后就可以进行排序了。

此时3位于堆顶不满堆的性质,则需调整继续调整

 这样整个区间便已经有序了。
    从上述过程可知,堆排序其实也是一种选择排序,是一种树形选择排序。只不过直接选择排序中,为了从R[1...n]中选择最大记录,需比较n-1次,然后 从R[1...n-2]中选择最大记录需比较n-2次。事实上这n-2次比较中有很多已经在前面的n-1次比较中已经做过,而树形选择排序恰好利用树形的 特点保存了部分前面的比较结果,因此可以减少比较次数。对于n个关键字序列,最坏情况下每个节点需比较log2(n)次,因此其最坏情况下时间复杂度为 nlogn。堆排序为不稳定排序,不适合记录较少的排序。
 
测试程序
复制代码
/*堆排序(大顶堆) 2011.9.14*/ 

#include <iostream>
#include<algorithm>
using namespace std;

void HeapAdjust(int *a,int i,int size)  //调整堆 {
    int lchild=2*i;       //i的左孩子节点序号     int rchild=2*i+1;     //i的右孩子节点序号     int max=i;            //临时变量     if(i<=size/2)          //如果i不是叶节点就不用进行调整     {
        if(lchild<=size&&a[lchild]>a[max])
        {
            max=lchild;
        }    
        if(rchild<=size&&a[rchild]>a[max])
        {
            max=rchild;
        }
        if(max!=i)
        {
            swap(a[i],a[max]);
            HeapAdjust(a,max,size);    //避免调整之后以max为父节点的子树不是堆         }
    }        
}

void BuildHeap(int *a,int size)    //建立堆 {
    int i;
    for(i=size/2;i>=1;i--)    //非叶节点最大序号值为size/2     {
        HeapAdjust(a,i,size);    
    }    
} 

void HeapSort(int *a,int size)    //堆排序 {
    int i;
    BuildHeap(a,size);
    for(i=size;i>=1;i--)
    {
        //cout<<a[1]<<" ";        swap(a[1],a[i]);           //交换堆顶和最后一个元素,即每次将剩余元素中的最大者放到最后面 
          //BuildHeap(a,i-1);        //将余下元素重新建立为大顶堆           HeapAdjust(a,1,i-1);      //重新调整堆顶节点成为大顶堆    }
} 

int main(int argc, char *argv[])
{
     //int a[]={0,16,20,3,11,17,8};    int a[100];
    int size;
    while(scanf("%d",&size)==1&&size>0)
    {
        int i;
        for(i=1;i<=size;i++)
            cin>>a[i];
        HeapSort(a,size);
        for(i=1;i<=size;i++)
            cout<<a[i]<<"";
        cout<<endl;
    }
    return 0;
}
分享到:
评论

相关推荐

    堆排序算法实现

    ### 堆排序算法实现详解 #### 一、引言 堆排序是一种高效的排序方法,其核心在于构建和调整二叉堆(一种完全二叉树结构)。本篇文章将基于《算法导论》第六章的内容,深入探讨堆排序的实现原理,并通过具体的C语言...

    java堆排序原理及算法实现

    【Java堆排序原理】 堆排序是一种高效的排序算法,基于完全二叉树的堆数据结构。在Java中,堆排序能够实现原地排序,即不需要额外的存储空间,且时间复杂度为O(nlogn)。然而,由于它不是稳定的排序算法,相同元素的...

    堆排序算法原理

    本文将详细介绍堆排序的基本原理、实现步骤以及通过一个具体的例子来帮助读者理解这一算法。 #### 二、堆的概念 堆排序是基于堆的数据结构实现的一种比较排序算法。堆是一种特殊的完全二叉树结构,具有以下特点: ...

    C语言实现堆排序的算法

    堆排序是一种高效的排序算法,基于比较...总之,堆排序是计算机科学中一种重要的排序算法,理解其原理和C语言实现是提升编程能力的重要环节。通过熟练掌握堆排序,我们可以更有效地处理大量数据,提高程序的运行效率。

    c语言实现堆排序算法

    本篇文章将详细介绍如何使用C语言实现堆排序算法,并通过代码示例深入理解其工作原理。 #### 堆排序算法原理 在堆排序中,首先需要构建一个大顶堆(或小顶堆),然后将堆顶元素与堆尾元素交换,将最大的元素“沉”...

    堆排序算法简单实现

    下面我们将详细讨论堆排序的原理、步骤以及其实现。 首先,我们需要理解堆的概念。在计算机科学中,堆通常被用作优先队列的数据结构。堆可以分为两种类型:最大堆(大顶堆)和最小堆(小顶堆)。最大堆的每个父节点...

    7大排序算法实现程序(快速排序,冒泡排序,选择排序,归并排序,插入排序,希尔排序,堆排序)

    本资源提供了七大经典排序算法的实现程序,包括快速排序、冒泡排序、选择排序、归并排序、插入排序、希尔排序和堆排序。下面将逐一详细介绍这些排序算法及其原理。 1. 快速排序:由C.A.R. Hoare提出,是一种采用...

    堆排序算法实现堆排序

    三、堆排序的算法实现 以下是一个简单的C++实现堆排序的例子: ```cpp #include using namespace std; void heapify(int arr[], int n, int i) { int largest = i; // 初始化最大值为根节点 int left = 2 * i ...

    堆排序算法实例

    堆排序是一种基于比较的排序算法,它通过构造一个近似完全二叉树的堆数据结构来实现排序。在计算机科学中,堆是一个可以被看作是一棵树形结构的数据集合,其中每个父节点的值都大于或等于其子节点的值(大顶堆)或...

    堆排序算法分析及源代码

    在黄进宗提供的文件中,可能包含了这些功能的实现,包括详细的注释和示例,帮助读者理解堆排序的工作原理和实现细节。通过阅读和分析这段源代码,你可以更深入地了解堆排序算法,并可能学习到如何在实际编程项目中...

    python 堆排序原理及代码实现

    Python 堆排序原理及代码实现 Python 堆排序是一种高效的排序算法,其基本思想是将待排序的序列构造成一个大顶堆。此时,整个序列的最大值就是堆顶的根节点。将它移走(其实就是将其与堆数组的末尾元素交换,此时...

    排序算法之堆排序算法:用C++语言实现堆排序算法

    标题"排序算法之堆排序算法:用C++语言实现堆排序算法",意味着我们将讨论如何用C++编程语言来实现堆排序的过程。C++是面向对象的编程语言,具有丰富的库支持和高效的执行性能,是实现算法的理想选择。 描述"排序...

    堆排序的非递归算法分析与JAVA实现

    在实现堆排序的过程中,理解这些知识点对于掌握堆排序的原理和非递归实现方法至关重要。通过分析堆的性质,理解堆排序的步骤和函数实现,以及了解数据库中间件和视图的作用,学习者可以更深入地理解数据结构和数据库...

    C++实现的一个堆排序算法

    ### C++实现的堆排序算法知识点解析 #### 一、堆排序基本概念 堆排序(Heapsort)是一种基于比较的排序技术,它利用了完全二叉树的特性来进行数据的排序。堆排序分为两个阶段:构建初始堆与排序过程。 - **构建...

    堆排序算法解析:原理、实现与优缺点

    堆排序是一种基于堆数据结构的选择排序算法,能够在 O(n log n) 时间复杂度下完成排序。堆是一个完全二叉树,且...本文详细介绍了堆排序的实现过程、时间复杂度分析以及优缺点,适合对算法实现和性能分析感兴趣的读者。

    堆排序算法详细配图讲解

    通过具体的例子验证算法的正确性,并提供详细的注释说明,有助于其他开发者理解和学习堆排序算法的实现原理。 堆排序算法的效率依赖于树的高度,由于堆是完全二叉树,它的高度大约是logn。因此,堆排序的性能不会...

    C++实现常用排序算法(快速,归并,选择,谢尔,堆排序)

    本文将深入探讨五种常用的排序算法:快速排序、归并排序、选择排序、谢尔排序和堆排序。 **快速排序** 是由C.A.R. Hoare在1960年提出的,是一种效率较高的分治策略。其基本思想是通过一趟排序将待排序的数据分割成...

    堆排序的c++实现代码

    `make_heap()`、`pop_heap()`和`sort_heap()`等函数在STL中提供了更简洁的实现方式,但为了更好地理解堆排序的工作原理,这里选择了手动构建和调整堆的实现。 堆排序的时间复杂度为O(nlogn),空间复杂度为O(1),是...

    堆排序 算法实验 C#实现的

    堆排序是一种高效的排序算法,基于完全二叉树的特性,其主要原理是通过构建最大(或最小)堆来实现数据的排序。在C#中实现堆排序,我们需要理解堆的基本概念,包括如何建立堆、调整堆以及如何进行元素的交换。 1. *...

Global site tag (gtag.js) - Google Analytics