堆排序--数据结构排序1

本文详细介绍了堆排序算法的基本原理和实现过程。包括堆排序的思想、性能分析、步骤详解以及C++代码实现。通过本文,读者可以了解到堆排序如何利用堆的性质进行排序,以及其在不同场景下的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

堆排序
堆排序是选择排序的一种,是利用堆的性质进行排序,如果需要升序排序,选择大顶堆。如果是降序排序,选择小顶堆。

堆排序思想
堆排序的思想就是堆的性质进行排序。分为无序区和有序区,将堆顶元素与最后一个一个元素进行兑换,扩大有序区,减少无序区。另外,注意堆是完全二叉树,因此如果是数组的话,数组元素对应的就是完全二叉树的层次遍历。
堆排序的性能

时间复杂度:O(nlogn)
空间复杂度:O(1)
不稳定排序
时间复杂度解析。我们在每次重新调整堆时,都要将父节点与孩子节点比较,这样,每次重新调整堆的时间复杂度变为O(logn),而堆排序时有n-1次重新调整堆的操作,建堆时有((len-1)/2+1)次重新调整堆的操作,因此堆排序的平均时间复杂度为O(n*logn)。由于我们这里没有借用辅助存储空间,因此空间复杂度为O(1)。
堆排序在排序元素较少时有点大才小用,待排序列元素较多时,堆排序还是很有效的。另外,堆排序在最坏情况下,时间复杂度也为O(n*logn)。相对于快速排序(平均时间复杂度为O(n*logn),最坏情况下为O(n*n)),这是堆排序的最大优点。
堆排序步骤
1.初始化堆。
2.交换堆中第一个元素和最后一个元素,然后对无序区进行调整,即调整堆。
大顶堆
对于根节点,num[i],如果num[i]>num[2*1+1] 并且 num[i]>num[2*1+2],则为大顶堆,即堆顶元素大于任何一个孩子节点。
小顶堆
与大顶堆相反。

堆排序代码C++

#include <iostream>

/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;
/**
HeapAdjust是对堆进行调整
parent是堆的顶点,
num是需要排序的数组,
len是待排序的数组长度 
*/
void HeapAdjust(int num[],int parent,int len){
    int temp = num[parent];//临时记录堆顶元素 
    int child = parent*2+1;//二叉树的性质,根节点为i,左孩子节点为2*i+1,有孩子节点为2*i+2
    while(child<len){//孩子节点不能超过长度
        //判断左孩子大还是右孩子大
        if(child+1<len && num[child]<num[child+1]){
            child++;//变成右孩子 
        } 
        //如果不需要更换parent对应的值,直接结束循环,此步骤一定不能省略 
        if(num[child]<temp){
            break;
        }
        //把根节点的数数值变成孩子中较大的
        num[parent]=num[child];
        //循环找出temp需要放的位置
        parent = child;
        child = child*2 +1; 
    } //循环结束就是找到了temp需要放的位置
    num[parent]=temp; 
}
void HeapSort(int num[],int len){
    //初始化建立堆,i是第一个非叶子节点的编号
    //第一个非叶子节点的位置序号为(len-1)/2   
    for(int i=(len-1)/2;i>=0;i--){
        HeapAdjust(num,i,len);//i为parent    
    } 
    for(int i=len-1;i>=0;i--){//第一个与最后一个交换,所以i为len-1更简单 
        int temp = num[i];
        num[i]=num[0];
        num[0]=temp;
        HeapAdjust(num,0,i);//从0-i需要调整,剩下的都已经是有序的啦 
        //堆排序的输出 
        cout<<"第"<<len-i<<"趟排序结果如下"<<endl; 
        for(int i=0;i<len;i++){
            cout<<num[i]<<" ";
        }
        cout<<endl;
    }       
}
int main(int argc, char *argv[]) {
    int len;//输入需要排序的数组的长度 
    cin>>len;
    int num[len];
    for(int i=0;i<len;i++){//输入排序数组 
        cin>>num[i];
    }
    HeapSort(num,len);//堆排序 
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值