6-1 堆排序

实现堆排序,函数void HeapAdjust(SqList &L,int s,int m)为筛选法调整堆,函数void CreatHeap(SqList &L)把无序序列L.r[1..n]建成大根堆,函数void HeapSort(SqList &L)对顺序表L进行堆排序。

实现堆排序,函数void HeapAdjust(SqList &L,int s,int m)为筛选法调整堆,函数void CreatHeap(SqList &L)把无序序列L.r[1…n]建成大根堆,函数void HeapSort(SqList &L)对顺序表L进行堆排序。

函数接口定义:
void HeapAdjust(SqList &L,int s,int m);//筛选法调整堆
void CreatHeap(SqList &L); //把无序序列L.r[1..n]建成大根堆
void HeapSort(SqList &L);//对顺序表L进行堆排序
裁判测试程序样例:

```cpp
#include <iostream>
#define MAXSIZE 1000
using namespace std;

typedef struct
{
 int key;
 char *otherinfo;
}ElemType;
                    
typedef struct
{
 ElemType *r;
 int  length;
}SqList;
                            
void Create_Sq(SqList &L)
{
 int i,n;
 cin>>n;    //输入的值不大于 MAXSIZE
 for(i=1;i<=n;i++)
 {
  cin>>L.r[i].key;
  L.length++;
 }
}
void show(SqList L)
{
 int i;
 for(i=1;i<=L.length;i++)
  if(i==1) 
   cout<<L.r[i].key;
  else
   cout<<" "<<L.r[i].key;
}

void HeapAdjust(SqList &L,int s,int m);//筛选法调整堆
void CreatHeap(SqList &L); //把无序序列L.r[1..n]建成大根堆
void HeapSort(SqList &L);//对顺序表L进行堆排序

int main()
{
 SqList L;
 L.r=new ElemType[MAXSIZE+1];
 L.length=0;
 Create_Sq(L);
 HeapSort(L);
 show(L);
 return 0;
}
/* 请在这里填写答案 */

输入样例:

第一行输入一个数n(输入的值不大于 MAXSIZE)
第二行依次输入n个数

9
30 45 53 78 65 9 12 17 23
输出样例:

输出升序排列的结果

9 12 17 23 30 45 53 65 78

代码长度限制 16KB
时间限制 400ms
内存限制 64MB

代码如下

// 堆化,保持堆的性质
// 从元素L.r[i].key,L.r[lt].key,L.r[rt].key中找出最大的,并将其下标保存在largest中。
// 如果L.r[i].key是最大的,则以i为根的子树成已为最大堆,程序结束。
// 否则,i的某个子节点中有最大元素,则交换L.r[i].key,L.r[largest].key从而使i及其子女满足堆性质。
// 下标为largest的结点在交换后的值为L.r[i].key,以该结点为根的子树又有可能违反最大堆性质。因而要对该子树递归调用HeapAdjust。
void HeapAdjust(SqList &L, int i, int size)
{   

 int lt = 2*i, rt = 2*i+1;
 int largest;
 if(lt <= size && L.r[lt].key > L.r[i].key)      //右孩子没有超过结点总数,且右孩子大于根节点。
  largest = lt;                  //便把右孩子的下标记下来,给最大值下标
 else
  largest = i;                   //否则把根节点的下标记下来,给最大值下标
 if(rt <= size && L.r[rt].key > L.r[largest].key)   /*再和左孩子的值进行比较。左孩子没有超过结点总数,且左孩子大于最大结点的值*/
  largest = rt;                          //将左孩子下标记下来,给最大值下标
 if(largest != i)                //如果最大值下标不是根节点,则进行key值的交换
 {
  int temp = L.r[i].key;
  L.r[i].key = L.r[largest].key;
  L.r[largest].key = temp;
  HeapAdjust(L, largest, size);       //继续调用HeapAdjust函数,进行最大堆的排序。
 }
}
 
// 建堆
/*自底而上地调用HeapAdjust来将一个数组a[1..size]变成一个最大堆.一定要自下而上的调用,
才能保证调用较小层次的结点的堆排序算法时,较高层次以及满足堆的性质。否则可能导致中间层次出现最大值。*/
// 注意: [size/2]以后的结点为叶子结点,即已经满足堆的性质
void CreatHeap(SqList &L)
{
 for(int i=L.length/2; i>=1; --i)      //当为满二叉树时,分支节点数n2,总结点数n=2n2+1,叶子节点数=n/2+1=n2+1
  HeapAdjust(L, i, L.length);
}
 
// 堆排序
// 初始调用CreatHeap将L.r[1..size].key变成最大堆
// 因为数组最大元素在L.r[1].key,则可以通过将L.r[1].key与L.r[size].key互换达到正确位置
// 现在新的根元素破坏了最大堆的性质,所以调用HeapAdjust调整,
// 使L.r[1..size-1].key成为最大堆,L.r[1].key又是L.r[1..size-1].key中的最大元素,
// 将L.r[1].key与L.r[size-1].key互换达到正确位置。
// 反复调用HeapAdjust,使整个数组成从小到大排序。
// 注意: 交换只是破坏了以L.r[1].key为根的二叉树最大堆性质,它的左右子二叉树还是具备最大堆性质。
//        这也是为何在CreatHeap时需要遍历size/2到1的结点才能构成最大堆,而这里只需要堆化L.r[1].key即可。
void HeapSort(SqList &L)
{
 CreatHeap(L );

 
 int len = L.length;
 for(int i=L.length; i>=2; --i)
 {
  int temp = L.r[1].key;
  L.r[1].key = L.r[i].key;
  L.r[i].key = temp;     /*因为最大堆只能保证第一个元素L.r[1].key是最大值,不能保证最后一个元素是最小值*/
  len--;                 /*所以只能通过每次把最大值,也就是L.r[1].key放在数组末尾,才能得到从小到大的序列*/
  HeapAdjust(L, 1, len);  /*不包括已排好序的L.r[len]后面的数组元素,在未排好序的部分做最大堆的算法*/

 }
 
}
 


在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

罗娜mei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值