数据结构之堆排序

#include <iostream>
using namespacestd;
/*
  将根节点root筛选成最大结点,注意root的【左右孩子】(root不用满足,不然就不用sift了)必须满足堆的性质了(即父节点必须大于左右孩子),最初拿到数据时,我们  是从倒数第一个有孩子的结点(n/2)开始的,而他的孩子是叶子,叶子满足堆的性质。

*/
void sift(int src[],introot,intn)
{
    // 父结点,左右孩子的索引
    int parent =root;
    int lchild =parent*2;
    int rchild =parent*2+1;
 

    // 保存最大孩子的数据
    int max_child;

    
    // 保存最大孩子的索引,每次父节点跟左右孩子交换的时候,有可能会破坏子树的堆性质
    // 当然只破坏左右子树中和父结点交换的那一棵而已
    int max_child_index;

    
    // 保存根结点的数据,每次父结点小于孩子结点的时候不需要跟孩子交换数据
    // 只需要将孩子的数据复制到父结点就行了
    int root_data =src[root];
    // 如果存在左孩子
    while(lchild <=n)
    {
       // 存在有孩子
       if(rchild <=n)
       {
           //左孩子大于右孩子
           if(src[lchild]>src[rchild])
           {
              max_child = src[lchild]; 
              max_child_index =lchild;  
           }
           //右孩子大于左孩子
           else
           {
              max_child = src[rchild];
              max_child_index =rchild;
           }
           //左右孩子中最大的孩子大于父节点
           if(max_child >root_data)
           {
              src[parent] =max_child;
              parent = max_child_index;
           }
           else
           {
              break;
           }
       }
       else
       {
           if(src[lchild]>root_data)
           {
              src[parent] =lchild;
              parent = lchild;
           }
           else
           {
              break;
           }
       }
       lchild= parent*2;
       rchild= parent*2+1;
    }
    src[parent] =root_data;
}
 

void build(int src[],intn)
{
    // 一棵有n个结点的树,n/2之后的所有都是叶结点
    for(introot =n/2;root >=0; --root)
    {
       sift(src,root,n); 
    }
}
 

void heapSort(int src[],intn)
{
    // 将树初始化为堆
    build(src,n);
    for(inti =n;i >= 0;--i)
    {
       // 输出根结点
       cout<<src[0]<<"";
       // 将最后一个放到根结点,顺便把树的结点数目减一
       src[0]= src[n--];
       // 再将根结点的堆性质被破坏的数重新筛选成堆
       sift(src, 0,n);
    }
    cout<<endl;
}

 
int main()
{
    int src[10] = {4,5,6,7,8,9,1,2,3,0};
    int n = 9;
    //int src[6] = {2,5,4,3,1,6};
    //int n= 5;
    heapSort(src,n);
    return0;
}


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值