堆排序算法原理,实现及时间复杂度分析

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

#include<iostream>
using namespace std;

int rcount=0;
int scount=0;
int successchange=1;

void output(int *a,int size){
    for(int i=1;i<=size;i++){
        cout<<a[i]<<' ';
    }
    cout<<endl;
}

bool judge(int i,int size){//judge if is a leaf node
    return i<=size/2;
}

bool hasRightChild(int i,int size){
    return 2*i+1<=size;
}

bool swap(int *a,int i,int size,int*which){//which means which child is changed
    scount++;
    int q=a[i];
    if(hasRightChild(i,size)){
        if(q>=a[2*i]&&q>=a[2*i+1])return false;
        if(a[2*i]>a[2*i+1]){
            a[i]=a[2*i];a[2*i]=q;*which=2*i;
        }else{
            a[i]=a[2*i+1];a[2*i+1]=q;*which=2*i+1;
        }
        return true;
    }else{
        if(q>=a[2*i])return false;
        a[i]=a[2*i];a[2*i]=q;*which=2*i;return true;
    }
}

void p(int*a,int i,int size,int time){//time means which time to adjust
    rcount++;
    int which=-1;
    if(judge(i,size)){
        //i maybe just has one left child
        if(a[i]>=a[2*i]&&a[i]>=a[2*i+1]&&time!=0)return;
        if(hasRightChild(i,size)&&judge(2*i+1,size)){//not leaf node
            if(time==0){
                p(a,2*i+1,size,time);
            }else if(a[i]<a[2*i+1]){
                p(a,2*i+1,size,time);
            }
        }
        if(time==0){
            if(judge(2*i,size))p(a,2*i,size,time);//not leaf node
        }else if(a[i]<a[2*i]){
            if(judge(2*i,size))p(a,2*i,size,time);//not leaf node
        }
        if(swap(a,i,size,&which))p(a,which,size,time);//p(a,i,size);
    }else{
        if(i%2==1&&!(size==1&&i==1)){//(size==1&&i==1) used to limit overflow
            if(time==0){
                if(judge(i-1,size))p(a,i-1,size,time);//not a leaf node
                if(swap(a,(i-1)/2,size,&which))p(a,which,size,time);
            }else if(a[(i-1)/2]<a[i-1]){
                if(judge(i-1,size))p(a,i-1,size,time);//noe a leaf node
                if(swap(a,(i-1)/2,size,&which))p(a,which,size,time);
            }
        }
    }
}


void workout(int *a,int size){
    if(size==1)return;
    int n=size;
    int tmp=0;

    for(int i=0;i<n;i++,size--){
        successchange=0;
        p(a,1,size,size!=n);
        tmp=a[size];a[size]=a[1];a[1]=tmp;
//        cout<<"this is loop "<<i<<":";
//        output(a,n);
    }
}



int main(int argc,char**argv){

    //int a[]={-1,16,7,3,20,17,8};
    //int size=6;

    //int a[]={-1,2,2,4,9,3,6,7,1,5};
    //int size=9;

    //int a[]={0,10,9,8,7,6,5,4,3,2,1};
    //int size=10;

    //int a[]={0,1,2,3,4,5,6,7,8,9,10};
    //int size=10;

    //int a[]={0,10,9};
    //int size=2;

    int a[101];
    for(int i=1;i<101;i++)a[i]=100-i;
    int size=100;

    cout<<"origin is:\t";output(a,size);
    workout(a,size);
    cout<<"after sort:\t";output(a,size);
    cout<<"recurve call count:"<<rcount<<endl;
    cout<<"swap call count:"<<scount<<endl;

    return 0;
}

运行结果如下:
运行结果

别人的堆排序实现算法:

/*堆排序(大顶堆) 2011.9.14*/

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

int rcount=0;
int scount=0;

void HeapAdjust(int *a,int i,int size)  //调整堆
{
    rcount++;
    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]);scount++;
            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[101];
    int size=100;
    for(int i=1;i<=100;i++)a[i]=100-i;
        HeapSort(a,size);
        for(int i=1;i<=size;i++)
            cout<<a[i]<<" ";
        cout<<endl;

        cout<<"recurve count is:"<<rcount<<endl;
        cout<<"swap count is:"<<scount<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值