排序之堆排序

9 篇文章 0 订阅

堆排序是一种基于比较排序的另一种排序算法,它采用了一种近似完全二叉树的二叉堆数据结构。算法实现兼容了插入排序的空间原址性(即只需要有限个额外的存储空间)和归并排序的优良时间复杂度。

伪代码如下:

HEAPSORT(A)

BUILD-MAX-HEAP(A)
for i = A.length downto 2
    exchange A[1] with A[i]
    A.heap-size = A.heap-size - 1
    MAX-HEAPIFY(A, 1)

BUILD-MAX-HEAP(A)

A.heap-size = A.length
for i = floor(A.length / 2) downto 1
    MAX-HEAPIFY(A, i)

MAX-HEAPIFY(A, i)

l = LEFT(i)
r = RIGHT(i)
if l <= A.heap-size and A[l] > A[i]
    largest = l
else largest = i
if r <= A.heap-size and A[r] > A[largest]
    largest = r
if largest != i
    exchange A[i] with A[largest]
    MAX-HEAPIFY(A, largest)

分析:

首先要明白什么是二叉堆,它的左右孩子是什么。

a.堆排序的核心子程序就是MAX-HEAPIFY(A, i),称作最大堆的维护。输入为数组A,和一个下标i,i的左孩子和右孩子都满足最大堆的性质,但A[i]可能小于其孩子,于是需要重新定位A[i]的位置,使其保持最大堆的性质。代码过程为:先找出A[i],A[left[i]],A[right[i]]的最大值,然后将最大值与A[i]交换。然后递归的交换,到最后每一个节点i都满足 A[left(i)]A[i] A[right(i)]A[i]

b.堆排序首先要创建一个最大堆。在子程序BUILD-MAX-HEAP(A)中,由于A(n/2+1..n)中的元素都是树的叶结点,所以只需要把前n/2个数插入到这个最大堆中,然后每插入一个数进行最大堆维护,当这n/2个数插完后,所得的数组就是一个最大堆。

c.堆排序主程序,先把所要排序的数组转化成最大堆,由于根位置的数就是最大的数,所以每次取根上的数放在数组的最后面,然后其余n-1个数维护后又成为最大堆,再取此时根上的数,直到只剩最后一个数,所得到的数组就是排好序的数组。

d.最大堆维护的时间复杂度为 T(n)=O(lgn) ,因为每个孩子的子树的大小至多为 2n/3 ,节点左右孩子的高度至多差1,所以 T(n)T(2n/3)+θ(1) ,得出 T(n)=O(lgn) 。建堆需要调用 n/2 次堆维护,所以需要 O(nlgn) 。所以堆排序总时间为:调用一次建堆, n1 次堆维护。所以总共时间复杂度为 O(nlgn)

C++代码实现

#include <iostream>
using namespace std;

void max_heapify(int*, int, int);
void heapsort(int*, int);

int main()
{
    int A[] = {2, 3, 6, 23, 3, 14, 0, 7, 32, 5, 3};
    int length = sizeof(A)/sizeof(int);
    int heap_size = length;
    heapsort(A, heap_size);
    for(int i = 0; i < length; i++)
    {
        cout<<A[i]<<" ";
    } 
    cout<<endl;
    return 0;
}

void max_heapify(int* A, int i, int heap_size)
{
    int l = i * 2 + 1;
    int r = l + 1;
    int largest;
    if(l < heap_size && A[l] > A[i])
        largest = l;
    else largest = i;
    if(r < heap_size && A[r] > A[largest])
        largest = r;
    if(largest != i)
    {
        int t = A[i];
        A[i] = A[largest];
        A[largest] = t; 
        max_heapify(A, largest, heap_size);
    }
}

void heapsort(int* A, int heap_size)
{
    int length = heap_size;//这里用length = sizeof(A)/sizeof(int)得出length等于1
    for(int i = length/2 - 1; i >= 0; i--)
    {
        max_heapify(A, i, heap_size);
    }

    for(int i = length-1; i > 0; i--)
    {
        int t = A[0];
        A[0] = A[i];
        A[i] = t;
        heap_size--;
        max_heapify(A, 0, heap_size);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值