堆排序算法,精简

博客提及排序算法相关内容,回顾19年按“父节点下面的左右子节点”方式对数组倒序比较父节点并交换子父节点的寻址做法,认为当时做法较费脑,还给出原理和流程图参考链接。

19年

数组倒序比较其父节点,并交换适当情况下的子节点与父节点:

#include<iostream>
#include<functional>
using namespace std;
bool compare(int &a,int &b){
    return a<b;
}
// void heap_sort(int (&arr)[8],int istart,int iend,bool (*compare)(int&,int&)){
void heap_sort(int (&arr)[8],int istart,int iend,std::function<bool (int&,int&)> compare){
    if(istart>=iend)    return;
    for(int i(iend);i>istart;i--){
        if(compare(arr[i-istart],arr[(i-istart+1)/2-1]))
            std::swap(arr[i-istart],arr[(i-istart+1)/2-1]);
    }
    std::swap(arr[istart],arr[iend]);
    heap_sort(arr,istart,iend-1,compare);
}
int main(int argc,char **argv){
    int arr[]={3,1,4,1,5,9,2,6};
    int len(7);
    heap_sort(arr,0,len,compare);
    for(int i(0);i<=len;i++)
        cout<<arr[i]<<' ';
    cout<<endl;
}

21 年:

这是19年脑子抽非要按“父节点下面的左右子节点”方式来寻址的做法,现在回头看就是有点废脑子:

原理和流程图参见https://www.cnblogs.com/chengxiao/p/6129630.html

//堆排序
void heapSort(int arr[],int nsize){ 
    if(nsize<=1)return;
    //arr退化成指向当前子数组(堆)的首元素的指针,nsize是当前子数组的维数
    int iM(ceil((nsize-1-2)/2)); //最后一个非叶子节点
    while(iM>=0){
        if(iM*2+2>(nsize-1)){ //没有右子节点
            if(arr[iM]>=arr[iM*2+1]) ;
            else swap(arr[iM],arr[iM*2+1]);
            iM--;
            continue;
        }
        if( arr[iM]>=arr[iM*2+1]&&arr[iM]>=arr[iM*2+2] ) ;
        else{
            //如果arr[iM*2+1]==arr[iM*2+2]的话移动arr[iM+1]保持稳定
            if(arr[iM*2+1]>=arr[iM*2+2]) swap(arr[iM],arr[iM*2+1]); 
            else swap(arr[iM],arr[iM*2+2]); 
        }
        iM--;
        continue;
    }
    { //构建最大堆
        // heapSort(++arr,--nsize);
    }
    { //构建最小堆
        swap(arr[0],arr[nsize-1]);
        heapSort(arr,--nsize);
    }
}
void func9(){
    int arr[]={3,1,4,1,5,9,2,6};
    heapSort(arr,8);
    for(int &rele:arr)std::cout<<rele<<"\t";
    std::cout<<"\n";
}

22 年:

#include<iostream>
using namespace std;
/*
len = 4,最后一个非叶子节点下标(int)(len-1)/2
        0
    1       2
3     _  _      _

len = 5,最后一个非叶子节点下标(int)(len-1)/2
        0
    1       2
3      4 _      _

len = 6,最后一个非叶子节点下标(int)(len-1)/2
            0
        1       2(i)
    3     4   5(i*2+1)  6((i+1)*2)
7     8 _
*/
bool heap_sort(int arr[],int len)
{
    if(len <= 1)
        return true;
    int i = (int)(len-1)/2; // 最后一个非叶子节点下标
    while(i>=0)
    {
        int ileft = i*2+1, iright = (i+1)*2;
        if(iright<len && arr[i]<arr[iright]) // 有右子节点,不swap想等元素就是保持原位了
            std::swap(arr[i],arr[iright]);
        if(ileft<len && arr[i]<arr[ileft])  // 有左子节点
            std::swap(arr[i],arr[ileft]);
        i--;
    }
    std::swap(arr[0],arr[len-1]);
    heap_sort(arr,len-1);
    return true;
}
#define COUNT 8
int main(int argc,char* argv[])
{
    int arr[] = {3,1,4,1,5,9,2,6};
    heap_sort(arr,COUNT);
    for(int i=0;i<COUNT;i++)
        cout<<arr[i]<<' ';
    cout<<endl;
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值