算法复习(1) 堆排序

堆是一种完全二叉树结构,以数组储存

堆的最后一层从左开始填充

对于元素个数为n的堆来说,高度为 floor(lgn)

对于给定下标i (从0开始),父节点,左儿子,右儿子分别为:

PARENT(i)
    return (i-1)>>1
LEFT(i)
    return 2i+1
RIGHT(i)
    return 2i+2

堆排序主体为3个函数:
Heapify、BuildHeap、Sort
Heapify用来保持某个特定节点及其所有子节点的最大/最小堆性质
BuildHeap用来将整个数组构建为最大/最小堆
Sort将数组排序,并毁坏最大/最小堆结构

//以最大堆为例
//这里不做边界检查
void Heapify(int * arr, int index, size)
{
    int left = LEFT(index);
    int right = RIGHT(index);
    int largest = index;
    if (left < size && arr[left] > arr[index])
        largest = left;
    else
        largest = index;
    if (right < size && arr[right] > arr[index])
        largest = right;
    if (largest != index)
    {
        int t = arr[largest];
        arr[largest] = arr[index];
        arr[index] = t;
        Heapify(arr, largest, size);
    }
}

void BuildHeap(int* arr, int size)
{
    int i = int(size/2)
    while(i--)
        Heapify(arr, i, size);
}

void Sort(int* arr, int size)
{
    while(size >= 0)
    {
        int t = arr[0];
        arr[0] = arr[size - 1];
        arr[size-1] = t;
        Heapify(arr, 0, --size);
    }
}

三个函数中关键在于BuildHeap是从最后一个拥有子节点的节点开始从下向上整理,而排序时每次都能以O(1)的代价找出最大值,再以O(lgn)代价恢复最大堆。

以最大/最小堆实现的最大/最小优先级队列是最大/最小堆的一个重要应用。
以最大堆为例
在之前的基础上添加了Maximum, ExtractMax, IncreaseKey(最小堆相应的为DecreaseKey), Insert 四个函数

int Maximum(int* arr)
{
    return arr[0];
}
int ExtractMax(int* arr, int size)
{
    int max = arr[0];
    int t = arr[0];
    arr[0] = arr[size-1];
    arr[size-1] = t;
    Heapify(arr, 0, --size);
}
bool IncreaseKey(int* arr, int index, int size, int key)
{
    if (arr[index] > key)
        return false;
    arr[index] = key;
    int i;
    while (i = PARENT(index) >= 0 && arr[i] < arr[index])
    {
        int t = arr[i];
        arr[i] = arr[index];
        arr[index] = t;
        index = i;
    }
    return true;
}
//代码不检查边界,但是在这里边界检查非常重要
bool Insert(int* arr, int size, int key)
{
    arr[size] = INT_MIN;
    ++size;
    IncreaseKey(arr, size-1, size, key);
}

最大/最小优先级队列在例如事件循环,工作调度中有显著的应用价值

但是对于最大/最小优先级队列,有一个问题:为什么在算法导论的介绍中不提供DecreaseKey(最大堆)和IncreaseKey(最小堆)?

就数据结构来说是完全可以做到的,代价也只是一次Heapify所带来的O(lgn)。我估计只是与最大/最小优先级队列的设计相违背所以不提供。实际工程应用中可能会有各种各样的需求,应当视实际情况重新设计。

若有不对,欢迎指出。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值