数据结构-堆排序

堆排序


  • 堆排序
    下面讨论利用堆进行排序的方法。可以分两种情况分别讨论:
    ① 如果初始序列是堆,则可通过反复执行如下操作而最终得到一个有序序列:
    输出根:即将根(第一个元素)与当前子序列中的最后一个元素交换。
    调整堆:将输出根之后的子序列调整为堆(元素个数比输出前少1个)。
    向下筛。
    ② 如果初始序列不是堆,则首先要将其先建成堆,然后再按 ① 的方式来实现。
    现在的问题是:如何由一个无序序列建成一个堆?
    向上筛。
    事实上,由无序序列建堆可通过反复调用筛选操作来实现。
    为此,需满足筛选的条件,即左右子树必须为堆。
    因此,建堆过程要从下往上逐棵子树地进行筛选。
    从易于编程的角度出发,根的下标自然是按从大到小,即根的下标按照从n/2到1的次序将各子树调整为堆。
    即:从最后一棵(最右边)高度为2的子树开始调整为堆。从右往左,自底向上(向总树根)逐层调整为堆。

【例】由初始序列(12,15,30,80,100,46,78,33,90,86,64,55,120,230,45)构建堆。
【解】首先由序列构建一棵完全二叉树,自最右高度为2的子树开始,然后从右往左,自底向上逐层调整为堆。
调整过程见后图。
<code>这里写图片描述</code>

代码块

#define maxlen 100
#define MaxSize 20

typedef int KeyType;    //定义关键字类型
typedef char InfoType[10];
typedef struct          //记录类型
{
    KeyType key;        //关键字项
    InfoType data;      //其他数据项,类型为InfoType
} RecType;              //排序的记录类型定义

class rank  
{
public:
    rank();
    virtual ~rank();
    RecType R[MaxSize];
//    int data[maxlen];
    int high;
    void shuru(int x);
    void shuchu();
    void sift(RecType R[],int low,int high);
    void heapsort(RecType R[],int n);
    void initlist();
};
#endif 
#include "stdafx.h"
#include "rank.h"
#include "iostream.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

rank::rank()
{

}

rank::~rank()
{

}
void rank::initlist()//录入
{
//  printf("please input some 数:\n");

    int i=1;
//    R[i]=0;
    while(EOF!=scanf("%d",&R[i]))     //输入数
    {
        i++;
        if(getchar()=='\n')
            break;
    }
    high= i-1;
//    printf("data[top]= %d\n",data[top]);
}


void rank::shuchu()
{
    for (int i=1; i<=high; i++)
        printf("%d ",R[i]);
    cout<<endl;
}

void rank::sift(RecType R[],int low,int high)
{
    int i=low,j=2*i;                        //R[j]是R[i]的左孩子
    RecType temp=R[i];
    while (j<=high)
    {
        if (j<high && R[j].key<R[j+1].key)  //若右孩子较大,把j指向右孩子//j变为2i+1
            j++;  //左孩子小于右孩子时,左右交换(左孩子要大于右孩子)
        if (temp.key<R[j].key)//双亲结点小于左孩子时,交换(双亲结点要大于左孩子)
        {
            R[i]=R[j];                          //将R[j]调整到双亲结点位置上
            i=j;                                //修改i和j值,以便继续向下筛选
            j=2*i;
        }
        else break;                             //筛选结束
    }
    R[i]=temp;   
}

void rank::heapsort(RecType R[],int n)
{
    int i;
    RecType temp;
    for (i=n/2; i>=1; i--) //循环建立初始堆
        sift(R,i,n);     //调整堆,形成75 57 48 40 19 34 38 11 6 13 9 7
    for (i=n; i>=2; i--) //进行n-1次循环,完成推排序
    {
        temp=R[1];       //将第一个元素同当前区间内R[1]对换 
        R[1]=R[i];
        R[i]=temp;       //最大值交换到最后
        sift(R,1,i-1);   //筛选R[1]结点,得到i-1个结点的堆 //前面的无序区调整为堆
    }   //调整堆
}
#include "stdafx.h"
#include "rank.h"
#include "iostream.h"

int main(int argc, char* argv[])
{
    rank r;
//  int x;
    cout<<"请随意输入一些数字: ";
    r.initlist();
    cout<<"数组长度为: "<<r.high<<endl;
    cout<<"未排序的结果为: ";
    r.shuchu();
    r.heapsort(r.R,r.high);
    cout<<"堆排序之后的结果为: ";
    r.shuchu();
//  printf("Hello World!\n");
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值