两种堆排序的比较

        堆排序是经典的排序问题中,非常重要的一种排序算法,实际上堆排序并没有特别之处,其主要的特点是将数组抽象成一个堆的结构。然后通过堆的二叉树性质进行排序。也正是由于利用了二叉树的性质,所以堆排序的时间复杂度能够达到O(nlogn)。

        下面的总结和比较,主要针对两种堆排序实现进行一个比较。突出两种实现方式对堆排序算法的细微区别和作者对算法的理解,实际上其本质是一样的。第一种是笔者参考机械工业出版社《数据结构》一书中,提出来的算法进行写的代码。两种实现方式中,算法效率更高效的是后者。

#include <iostream> 
#include <iomanip>
#include <cstdlib>
using namespace std;

void adjust(int array[],int root,int n) //这个调整的函数,效率有一些低,因为它每次都是从最后一个父节点,开始调整堆,实际上其实是不需要每一次都从最后一个父节点开始调整堆的,因为秩序对改变堆的地方进行重新调整堆的操作 
{
     int child;
     int rootkey = array[root];
     child = 2 * root;
     while(child<=n-1) //这个循环就是直接从堆排序中的二叉树的最后一个父节点,开始调整堆。 
     {
        if((child<n)&&(array[child]<array[child + 1]))//寻找左右子节点中,权值更大的那个子节点 
        child++;
        if(rootkey>array[child])//如果父节点的权值大,跳到下一个循环 
        break;
        else//如果子节点的权值,比父节点大,此时开始交换子节点和父节点的权值 
        {
            array[child/2] = array[child];
            child *= 2;
        }
     }
     array[child/2] = rootkey;
}
void heapsort(int array[],int n)
{
     int i,j;
     int temp;
     for(i=n/2;i>=0;i--)
     adjust(array,i,n);
     for(i=n-1;i>=0;i--)
     {
        temp = array[0];
        array[0] = array[i+1];
        array[i+1] = temp; 
        adjust(array,0,i);
     }
}

int main()
{
    const int NUM=20;
    int arr[] = {1,10,11,5,6,15,0,15,16,14,0,8,17,15,7,19,17,1,18,7};
    for(int i=0;i<20;i++)
    {
       cout<<arr[i]<<" ";
    }
    heapsort(arr,20);
    cout<<endl;
    for(int i=0;i<20;i++)
    {
       cout<<arr[i]<<" ";
    }
    system("PAUSE");
    return 0;
}

       第二种,是我从博客园上看到的一个博主写的帖子,我觉得很有意思,其对堆排序的理解其实是非常深刻的。下面就对他的方法做一个诠释和总结。这个实现的知识产权属于原作者:http://www.cnblogs.com/dolphin0520/archive/2011/10/06/2199741.html

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

void HeapAdjust(int* array,int i,int size)//与上述堆排序实现不同的就体现在这个调整堆的理解上,作者的实现其实只对需要调整的结点进行了堆调整 
{
     void Swap(int &a,int &b);
     int left = 2*i+1;
     int right = 2*i+2;
     int max = i;
     if(i<=size/2)//如果堆排序中的最大堆和最小堆建好了以后,每一次调整堆,如果某一个父节点与其子节点做了调整,实际上接下来的只需要对子节点所在的每一个小的二叉树进行调整,这个步骤比上面的调整堆算法要高效一些 
     {
         if((left<=size)&&(array[left]>array[max]))
         {
             max = left;
         }
         if((right<=size)&&(array[right]>array[max]))
         {
             max = right;
         }
         if(max != i)//如果当前进行了堆排序的调整,那么接下来做一个递归的调用,对子节点的小二叉树进行堆调整的操作,维持最大堆或者最小堆的性质 
         {
             Swap(array[i],array[max]);
             HeapAdjust(array,max,size);
         }  
     }  
}

void Swap(int &a,int &b)
{
     int temp = a;
     a = b;
     b = temp;
}

void BuildHeap(int *array,int size)
{
     for(int i = size/2;i>=0;i--)
     HeapAdjust(array,i,size);
}

void HeapSort(int *array,int size)
{
     void BuildHeap(int *array,int size);
     BuildHeap(array,size);
     for(int i=size;i>=0;i--)
     {
         Swap(array[0],array[i]);
         HeapAdjust(array,0,i-1);
     }   
}


int main(int argc,char** argv)
{
    int a[100];
    int size;
    cout<<"Please input the array:";
    while(scanf("%d",&size)==1&&size>0)
    {
        int i;
        for(i=0;i<=size-1;i++)
        {
           cout<<"Please input array["<<i<<"]:";
           cin>>a[i];                
        }
        HeapSort(a,size-1);
        cout<<"After Heap Sort,the Array is:"<<endl;
        for(i=0;i<=size-1;i++)
            cout<<a[i]<<" ";
        cout<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值