6-堆排序C实现(递增递减的简单转换,可优化(41行提示))

一、
主函数:void Hea_Sort(int* head,int low,int high,int Step_L,int Bool)
参数解释
head:数组指针
[low, high]:需排序的数组范围
Step_L:需排序步长
Bool:等于1表示从小到大排序,不等于1从大到小排序

主函数引用:void Hea_Adjust(int* head,int high,int Start,int Step_L,int Bool)
参数解释
head:数组指针
Start:需调整的位置
high:数组中能够进行调整的最高位置
Step_L:需排序步长
Bool:等于1表示从小到大排序,不等于1从大到小排序

说明
Step_L=1时
第一步对下标low+{0,1,2,3,4,5…}排序

Step_L=2时
第一步对下标low+{0,2,4,6,8,10…}排序

Step_L=3时
第一步对下标low+{0,3,6,9,12,15…}排序
以此类推

#include <stdio.h>
#include <time.h>
void Hea_Sort(int* head,int low,int high,int Step_L,int Bool);
void Hea_Adjust(int* head,int high,int Start,int Step_L,int Bool);

//堆排序
//需排序数组中第1个元素的位置为low
//需排序数组中第i个元素的位置为low+i*Step_L
//需排序数组中调整的开始位置为(L-1)/2(逻辑位置),low+(L-1)/2*Step_L(实际地址)
void Hea_Sort(int* head,int low,int high,int Step_L,int Bool){
    //创建根堆
    int Shigh=low+(((high-low+1)/Step_L)-1+(((high-low+1)%Step_L)!=0))*Step_L;//需排序的最后一个数的下标
    int L=(Shigh-low)/Step_L+1;//需排序数组长度
    int Start=low+(L/2-1)*Step_L;//Start为需调整位
    while(Start>=low){
            Hea_Adjust(head,high,Start,Step_L,Bool);
            Start-=Step_L;
        }
    printf("\n%d ",head[low]);//输出大根堆或小根堆的low处的最值
    
    //调整根堆
    head[low]=head[high];//将high处数据放到low处
    Start=low;//此时,已经是小根堆或大根堆,上一步使得仅有low处数据需要调整,于是将Start置为low
    high-=Step_L;//需调整的位置
    while(low<=high){
        Hea_Adjust(head,high,Start,Step_L,Bool);
        printf("%d ",head[low]);//输出大根堆或小根堆的最值
        head[low]=head[high];//将high处数据放到low处
        high-=Step_L;//能够进行调整的最高位置
    }
}

//调整函数,为上面堆排序所用
//Bool=1,小堆;Bool=0,大堆
void Hea_Adjust(int* head,int high,int Start,int Step_L,int Bool){
    int Left=Start+(Start+1)*Step_L;//左子
    int Right=Start+(Start+2)*Step_L;//右子
    int temp;//交换
    while(Left<=high){//左子存在,需要判断是否调整
        if(Right<=high){//一父二子比较:Start、Left、Right
            //简化可用(((head[Start]-head[Left])*(head[Start]-head[Right])<=0) || (((head[Start]>head[Left])==Bool) && ((head[Start]>head[Right])==Bool)))
            if(Bool){//小堆,与双子中最小的交换
                if(head[Start]>=head[Left] || head[Start]>=head[Right]){//选择交换子
                    if(head[Left]<=head[Right]){//选择左交换子
                        temp=head[Start];
                        head[Start]=head[Left];
                        head[Left]=temp;
                        Start=Left;//下一步需调整的位置
                    }else{//选择右交换子
                        temp=head[Start];
                        head[Start]=head[Right];
                        head[Right]=temp;
                        Start=Right;//下一步需调整的位置
                    }
                }
                else{
                    break;
                }
            }
            else{//大堆,与双子中最大的交换
                if((head[Start]<=head[Left] || head[Start]<=head[Right])){//选择交换子
                    if(head[Left]>=head[Right]){//选择左交换子
                        temp=head[Start];
                        head[Start]=head[Left];
                        head[Left]=temp;
                        Start=Left;//下一步需调整的位置
                    }else{//选择右交换子
                        temp=head[Start];
                        head[Start]=head[Right];
                        head[Right]=temp;
                        Start=Right;//下一步需调整的位置
                    }
                }
                else{
                    break;
                }
            }
        }
        else{//一父一子比较:Start、Left
            if(head[Start]>=head[Left]==Bool){//2021.10.09因为这里的”==”符号用了两小时寻找!!!
                temp=head[Start];
                head[Start]=head[Left];
                head[Left]=temp;
                Start=Left;//下一步需调整的位置
            }
            else{
                break;
            }
        }
        Left=Start+(Start+1)*Step_L;//更新左子
        Right=Start+(Start+2)*Step_L;//更新右子
    }
}














int main(int argc, char **argv) {
    printf("Hello, World!\n");
    int s[5];
    s[0]=2;
    s[1]=5;
    s[2]=1;
    s[3]=4;
    s[4]=3;
    
    int i=0;
    while(i<5)printf("%d ",s[i++]);
    
    printf("\n---------\n");
    Hea_Sort(s,0,4,1,0);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值