堆排序

堆排序与快速排序,归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法。学习堆排序前,先讲解下什么是数据结构中的二叉堆。

二叉堆的定义
:二叉堆是完全二叉树或者是近似完全二叉树。

二叉堆满足二个特性:

1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。

2.每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆)。

当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆。当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆。下图展示一个最大堆:

从图中可以看出

  1. 若父子结点下标为i,则左孩子的下标为i*2+1,右孩子的下标是i*2+2。
  2. 数组元素个数为size,则在下标size/2-1之后的结点都是叶子结点。
  3. 下标为size/2-1的结点是最后一个非叶子结点。
    ## 堆的插入删除 ##
    这是《数据结构C++语言描述》中最小堆的建立插入删除的图解。

    堆的插入
    由图可得,每次插入时都是从最后一个位置插,相当于将一个元素插入到有序的数组中去,则插入后一直向上调整直到0位置。
    代码如下
void HeapAdjustup(int a[],int i,int size)   //向上调整
{

    if(i > size)
        return ;
    int parent = (i-1)/2;
    int min = parent;
    if (parent <= size/2)   //不是叶子结点才调整
    {
        if(a[i] < a[min])
            min = i;
        if (min == parent)
        {
            swap(a[min],a[parent]);
            HeapAdjustup(a,parent,size);
        }
    }
}
void MinHeapFixup(int a[],int i)  ///循环代码
{
    for(int j = (i-1)/2 ; (j >0 && i != 0) && (a[i] > a[j]);i = j,j = (i-1)/2)
        swap(a[i],a[j]);
}
void InsertHeap(int a[],int size,int key)
{
    a[size] = key;
    HeapAdjustup(a,size,size+1);
}

以下图为例分析小堆建立的过程,以及堆排序的原理

参考代码如下

void HeapAdjust(int a[],int i,int size)///向下调整
{
    if (i >= size)
        return ;
    int left = 2*i+1;  //左孩子的下标
    int right = 2*i+2;//右孩子的下标
    int min = i;  //设置最小的下标为i
    if (i<=size/2) //不是叶子结点的才调整
    {
        if (left < size&&a[left] < a[min])     //找到它的左孩子右孩子以及自己中最小的那个
            min = left;
        if (right < size&&a[right] < a[min])
            min = right;
        if (min != i) //如果最小的不是自己,就交换
        {
            swap(a[i],a[min]);
            HeapAdjust(a,min,size);   //递归调整以min为父节点的子树
        }
    }
}

void CreateHeap(int a[],int size)
{
    for (int i = size/2-1;i>=0;--i)
        HeapAdjust(a,i,size);
}

删除的代码

void HeapAdjust(int a[],int i,int size)///向下调整
{
    if (i >= size)
        return ;
    int left = 2*i+1;  //左孩子的下标
    int right = 2*i+2;//右孩子的下标
    int min = i;  //设置最小的下标为i
    if (i<=size/2) //不是叶子结点的才调整
    {
        if (left < size&&a[left] < a[min])     //找到它的左孩子右孩子以及自己中最小的那个
            min = left;
        if (right < size&&a[right] < a[min])
            min = right;
        if (min != i) //如果最小的不是自己,就交换
        {
            swap(a[i],a[min]);
            HeapAdjust(a,min,size);   //递归调整以min为父节点的子树
        }
    }
}
void DeleteHeap(int a[],int size)
{
    swap(a[0],a[size-1]);
    HeapAdjust(a,0,size-1);
}

至此,堆排序的原理以及实现代码已经写完。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值