堆排序

堆排序

一、堆的性质:

堆是一个完全二叉树

1)若它的每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆

2)若它的每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆

因此,在堆的定义中可以发现:根结点的值一定是堆中所有结点的最大(最小)值

二、堆排序算法(以大顶堆为例)

基本思想:

1)将待排序的n个元素的序列构造成一个大顶堆。此时序列的最大值就是根结点的值;

2)将根结点移走(即将根结点与序列中的最后一个元素交换,在序列中就体现为最末尾元素就是最大值),

3)将剩余的(n-1)个元素的序列重新构造成一个大顶堆,重新按照2)的步骤执行


如此重复以上操作,一个随机的序列经堆排序就变成了递增的有序序列

三、复杂度分析

在构建堆的过程中,对于每一个有叶子结点的结点(n/2)来说,最多两次比较和一次互换操作,因此整个构建堆的复杂度为O(n);

在排序时,第i次取堆顶记录重建堆需要用O(logi)的时间(完全二叉树某个结点到根结点的高度为log(i)+1),并且需要取n-1次堆顶记录,因此,重建的复杂度为O(nlogn)。

堆排序过程演示视频【点击此处】

四、代码实现

/*******************************************************************************************
【堆排序】

Author:tmw
date:2017-11-4
update:2019-3-22
********************************************************************************************/
#include <stdio.h>
#include <stdlib.h>

#define swap(a,b,t) (t=a,a=b,b=t)

//将无序序列转变成大顶堆序列
//规定无序元素从数组的1号地址开始填
void heap_sort_one(int* array, int father_index, int array_len)
{
    int child_index=0;
    int temp=0;
    //child_index始终为孩子结点中较大值的下标
    for(child_index=father_index*2; child_index<=array_len; child_index=child_index*2)
    {
        /**这里的child+1是因为后面有个array[child_index+1] 防止溢出**/
        if(child_index+1<=array_len && array[child_index]<array[child_index+1])
            child_index++;//如果右孩子的值大于左孩子,则child_index为右孩子下标

        //孩子结点的值大于根结点的值---交换
        if(child_index<=array_len && array[father_index]<array[child_index])
        {
            swap(array[father_index],array[child_index],temp);
            father_index = child_index; //更新后继续更新孩子结点的左右子树
        }
    }
}

int* heap_sort_all(int* array, int array_len, int k)
{
    int i = 0;
    int temp = 0;

    /**建立一个array_len的大顶堆**/
    for(i=array_len/2; i>=1; i--)  /**!!!从下往上更新**/
        heap_sort_one(array,i,array_len);

    //将根结点取出(与序列最后一个元素换位置),重新对剩余元素再堆排序,如此重复
    for(i=array_len; i>0; i--)
    {
        swap(array[1],array[i],temp);
        heap_sort_one(array,1,i-1); /**!!!从根节点更新**/
    }
    return array;
}

int main()
{
    int *array;
    int i,array_size;
    printf("请输入数组元素的个数:\n");
    scanf("%d",&array_size);

    array = (int*)malloc(sizeof(int));
    printf("请输入 %d 个元素\n",array_size);
    for( i = 1 ; i <= array_size ; i++ )
        scanf("%d",&array[i]);

    array = heap_sort_all( array , array_size );
    printf("经堆排序后,数组元素顺序输出为:\n");
    for( i = 1 ; i <= array_size ; i++ )
        printf("%d ",array[i]);
    return 0;
}

 

五、程序运行结果

 


                                                                梦想还是要有的,万一实现了呢~~↖(^ω^)↗~~~~~

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值