堆排序(HeapSort)

堆排序使用一种称为“堆”的数据结构来进行信息管理。堆不仅用在堆排序中,还可以用来构造优先队列。

堆是一个数组,它可以被看成一个近似的完全二叉树,树上的每一个结点对应数组中的一个元素。

根据二叉树的性质可知,给定一个结点在数组中的下标i

双亲结点: Parent=floor(i/2);
左孩子结点: Left=i*2;
右孩子结点: Right=i*2+1;

二叉堆可以分为两种形式:

  1. 最大堆:双亲结点大于孩子结点
  2. 最小堆:双亲结点大于孩子结点
    最大堆用来进行从大到小的排序,最小堆用来进行从小到大的排序。

用来构造堆的函数:

1. Max_Heapify: 其时间复杂度为O(lgn),用来调整子树
2. BUlid_Max_Heap:具有线性时间复杂度,用来将无序的输入数据构造成一个最大堆
3. HeapSort:用来对一个数组进行原址排序

堆排序

对于一个最大堆,它的所有子树也均为最大堆。对于一个高度为2的子树,我们可以通过比较双亲结点与孩子结点的大小关系,然后依次来调整位置,最后递归调用(也就是说Max_Heapify包括了将子树调整为最大堆的过程),在这个过程中,可以想象到较小值可以一直下移,而较大值最多可以移到当前递归的子树的双亲结点。

void Max_Heapify(int* A,int i,int n){  
    int l=Left(i);
    int r=Right(i);
    int largest=0;
    if(l<n&&A[l]>A[i])  
        largest=l;
    else
        largest=i;
    
    if(r<n&&A[r]>A[i])
        largest=r;
    
    if(largest!=i){
        swap(A[i],A[largest]);
        Max_Heapify(A,largest,n);
    }

}

那么如何让较大值一直上移呢?我们可以从最底层的子树开始调整,从下往上调用Max_Heapify,这样操作的子树必然为最大堆。

Build_Max_Heap将较大值不断上移,Max_Heapify每一次调整都可以将较小值不断下移。

void Build_Max_Heap(int* A,int n){
    for(int i=floor(n/2);i>=1;i--)
        Max_Heapify(A,i,n);
}
#include<iostream>
#include<cmath>
#include<cstdlib>
using namespace std;
void HeapSort(int* A,int n);
int Parent(int i);
int Left(int i);
int Right(int i);
void Max_Heapify(int* A,int i,int n);
void Build_Max_Heap(int *A,int n);

int main(){
    int n;
    cin>>n;
    int *A=new int[n];
    for(int i=0;i<n;i++)
        A[i]=rand();
    HeapSort(A,n);

    for(int i=0;i<n;i++){
        cout<<A[i]<<" ";
    }
    delete A;
}

void HeapSort(int* A,int n){
    Build_Max_Heap(A,n);
    for(int i=n-1;i>=1;i--){
        swap(A[0],A[i]);
        n=n-1;
        Max_Heapify(A,1,n);
    }
}
int Parent(int i){
    return floor(i/2.0);
}

int Left(int i){
    return 2*i;
}
int Right(int i){
    return 2*i+1;
}


void Max_Heapify(int* A,int i,int n){  
    int l=Left(i);
    int r=Right(i);
    int largest=0;
    if(l<n&&A[l]>A[i])  
        largest=l;
    else
        largest=i;
    
    if(r<n&&A[r]>A[i])
        largest=r;
    
    if(largest!=i){
        swap(A[i],A[largest]);
        Max_Heapify(A,largest,n);
    }

}

void Build_Max_Heap(int* A,int n){
    for(int i=floor(n/2);i>=1;i--)
        Max_Heapify(A,i,n);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值