算法复习(1) 堆排序

来源:互联网 发布:ubuntu安装mysql失败 编辑:程序博客网 时间:2024/05/17 02:16

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

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

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

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

PARENT(i)    return (i-1)>>1LEFT(i)    return 2i+1RIGHT(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
原创粉丝点击