堆排序算法

堆——最大堆/最小堆的初始化、增加、删除等基本操作

堆是一种经过排序的完全二叉树或满二叉树
满二叉树即除最后一层无任何子节点外,每一层上的所有结点都有两个子结点的二叉树
堆排序运行的时间:O(nlog n)

1、示例:

如下为一个最大堆,用数组则可以按顺序表示堆{100,19,36,17,3,25,1,2,7}
这里写图片描述

2、堆初始化【堆排序的思想】

这里写图片描述
从一个无序序列初始化为一个堆的过程就是一个反复“筛选”的过程。由完全二叉树的性质可知,一个有n个节点的完全二叉树的最后一个非页节点就是n/2(比如9/2=4)节点开始。上图为无序数组{49,38,65,97,76,13,27,50}的初始化过程:

首先,未处理的数组对应的堆为图1模样。从第四个节点开始([8/2]=4),因为50 < 97,故要交换两节点,交换后还要继续对其新的左子树进行类似输出后那样的筛选。易见其左子树只有节点97,已经为最佳情况,故可以继续堆的初始化,如图2。再考虑第三个节点,因为13 < 27 < 65,即节点13为当前的最小节点,故与节点65交换,并对新的左子树进行筛选,其也为最佳情况,故可继续堆的初始化,结果如图3。然后考虑第二个节点,因为38 < 50 < 76,故已经为最优情况,不用调整。最后再考虑第一个节点,根节点。因为 13 < 38 < 49,故需要将根节点49与其右孩子节点13交换,交换后还要继续对其新的右子树进行类似输出后那样的筛选,可见右子树还需要调整,因为 27 < 49 < 65,故将节点49与节点27交换。此时已经处理完了根节点,初始化结束。最终结果如图5。

以下假设完成最大堆

3、元素上移操作

【参考《算法分析于与设计》P64】

//输入:数组以及需要被上移的元素下标i
template <class Type>
void sift_up(Type H[],int i)
{
    BOOL done=FALSE;
    if(i!=1){
        while(!done && i!=1){
            if(H[i]>H[i/2])
                swap(H[i],H[i/2]);
            else done=THRE;
            i=i/2;
        }
    }
}

4、元素下移操作

template <class Type>
void sift_down(Type H[],int i)
{
    BOOL done=FALSE;
    if((2*i)<=n){
        while(!done && (i=2*i)<=n){
            if((i+1<=n)&&(H[i+1]>H[i]))
                i=i+1;
            if(H[i]>H[i/2])
                swap(H[i/2],H[i]);
            else done=THRE;
        }
    }
}

5、元素插入操作

template <class Type>
void insert(Type H[],int &n,Type x)
{
    n=n+1;
    H[n]=x;
    sift_up(H,n);
}

6、元素删除操作

//输入:数组、数组的元素个数n,被删除的元素的下标
//输出:维持堆的性质的数组,以及删除后的元素的个数

template <class Type>
void delete(Type H[],int i)
{
    Type x,y;
    x=H[i];
    y=H[n];
    n=n-1;
    if(i<=n){
        H[i]=y;
        if(y>x)
            sift_up(H,i);
        else
            sift_down(H,n,i);
}

7、删除关键字最大元素

template <class Type>
Type delete_max(Type H[],int i)
{
    Type x;
    x=H[1];
    delete(H[],n,1);
    return x;
}

8、堆的建立

方法1

//堆的建立是指,把数组中的n个元素连续的使用插入操作插入队中
template <class Type>
void make_heap(Type A[],Type H[],int n)
{
    int i,m=0;
    for(i=0;i<n;i++)
        insert(H,m,A[i]);    //使用insert
}

方法2

template <class Type>
void make_heap(Type A[],int n)
{
    int i;
    A[n]=A[0];
    for(i=n/2;i>=1;i--)
        sift_down(A,i);
}

8、堆的排序

//输入:数组,元素个数
//输出:递增的数组
template <class Type>
void heap_sort(Type A[],int n)
{
    int i;
    make_heap(A,n);
    for(i=n;i>1;i--)
        swap(A[1],A[i];
        sift_down(A,i-1,1);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值