排序算法(3)-堆排序

堆排序的时间复杂度为O(nlgn),具空间原址性,主要特点是引入了堆的数据结构来信息管理。

一、堆的概念

了解堆的概念前了解几个相关的概念

1.相关概念:

image  image

满二叉树,每个结点为叶节点或者度为2. 完全二叉树,叶节点都在同一节,每个内部结点的度都为2.

image

结点的高度:结点到叶的简单路径的边数

结点的层次:根节点到节点的路径长度
树的高度:根节点的高度

二叉树的一些性质: 高度为d的二叉树结点数最多为 image 。结点数位n的二叉树高度至少为lgn向下取整。

2.堆(主要讨论最大堆,最小堆类似):

堆是一个接近完全的二叉树主要有两个特点(1),除了最后一个层次,其他层次都是完成,最后一个层次是从左到右充满的。(2),最大堆对于任意结点,符合父节点大于子节点Parent(x) ≥ x。

堆是怎么存储的呢?一个堆可以存储成一个数组。

image image

如图:右边为一堆,堆顶为a[1],i节点左孩子序号为2i;右孩子为2i+1;父节点为image 。其中image 为叶节点(叶节点数跟非叶几点相等),

 

 

二、堆的几个基本过程

1.max_heapify

这个过程主要是为了维护最大堆性质,使父节点大于左右子树节点,是一个递归的。这里要注意的一个地方是前提必须保证左右子树都已经满足最大堆的性质

imageimage image  image image

节点跟左右节点比较,记录最大节点的序号,若最大节点不是当前节点,将最大和当前节点交换,然后递归调用这个过程对被交换的子节点进行,直到到叶节点。程序

void max_heapify(int a[],int i,int heapsize)
{
    int l=2*i+1, r=2*i+2,largest=i;
    if (l<heapsize&&a[l]>a[i])
        largest=l;
    else largest=i;
    if (r<heapsize&&a[r]>a[largest])
        largest=r;
    if (largest!=i)
    {
        int temp=a[largest];
        a[largest]=a[i];
        a[i]=temp;
        max_heapify(a,largest,heapsize);
    }    
}

堆的高度heapsize由程序插入,l,r,定义左右节点的序号(数组序号从0开始,所以跟前面有些不同),两个if判断最大的在哪,然后判断最大是否为当前,不是,交换值。

运行时间,最坏就是沿着树根一直下到叶节点,每次都要比较2次,树的高度h=lgn,所以运行时间为O(lgn)。

2.build_max_heap

这个过程是输入一个序列,在上面构建一个最大堆,根据堆的性质image 都是叶节点满足堆的性质,所以只需要从1..image 间维护最大堆的性质就可以。

image

void build_maxheap(int a[],int heapsize)
{   
    
    for (int i=heapsize/2-1;i>=0;i--)
    {
        max_heapify(a,i,heapsize);
    }
}

是从heapsize/2…1。不是从1...heapsize/2。这是max_heapify的函数决定的,因为对某个节点维护最大堆的性质时,必须保证左右子树满足最大堆的性质,这样才能达到这个树具堆的性质。所以要至底向上一步步维护,使这个树有序。

3.heap_sort

堆排序,有了前面的基础,我们能够在一个序列上构建最大堆,根节点是序列的最大值,取出最大值与最后一个值交换,从树种删去这一点,然后维护最大堆性质,使最大值到根节点,不断循环。

image

程序:

void heap_sort(int a[],int heapsize)
{  
     build_maxheap(a,heapsize);
    for (int i=heapsize-1;i>=1;i--)
    {
        int temp=a[0];
        a[0]=a[i];
        a[i]=temp;
        max_heapify(a,0,i);
    }
}

 

整个程序

#include <iostream>
const int len=8;
using namespace std;
void max_heapify(int a[],int i,int heapsize)
{
    int l=2*i+1, r=2*i+2,largest=i;
    if (l<heapsize&&a[l]>a[i])
        largest=l;
    else largest=i;
    if (r<heapsize&&a[r]>a[largest])
        largest=r;
    if (largest!=i)
    {
        int temp=a[largest];
        a[largest]=a[i];
        a[i]=temp;
        max_heapify(a,largest,heapsize);
    }    
}
void build_maxheap(int a[],int heapsize)
{   
    
    for (int i=heapsize/2-1;i>=0;i--)
    {
        max_heapify(a,i,heapsize);
    }


}
void heap_sort(int a[],int heapsize)
{  
    build_maxheap(a,heapsize);
    for (int i=heapsize-1;i>=1;i--)
    {
        int temp=a[0];
        a[0]=a[i];
        a[i]=temp;
        max_heapify(a,0,i);
    }


}
int main()
{  
    int a[len]={2,8,7,1,3,5,6,4};
    heap_sort(a,8);

    for(int i=0;i<len;i++) cout<<a[i]<<" ";
    cout<<endl;
} //main end
posted @ 2014-08-01 11:42  dawnminghuang  阅读(291)  评论(0编辑  收藏  举报