堆排序(Heapsort)

来源:互联网 发布:锐速 原理 知乎 编辑:程序博客网 时间:2024/05/29 12:32

复杂度:O(nlog(n))
堆是一个数组,可以看做近似的完全二叉树;

对于给定的下标 i :
父节点的下标:i/2
左子节点的下标:2i
右子节点的下标:2i+1

最大堆:

除了根以外的结点满足:

a[Parent(i)] >= a[i]

维护堆的性质:
宏定义:

# define PARENT(i) (i/2)# define LEFT(i) (2*i)# define RIGHT(i) (2*i + 1)

多说一句,这里如果用堆排序的话,下标要从1开始了,因为如果i是0,LEFT(i)也是0,而左子节点应该是1,就会出现错误,所以数组下标的范围为 1 到 heap_size

MAX-HEAPIFY函数:

void MaxHeapify(int* a, int i, int heap_size) {    int maxn = i;    if (LEFT(i) <= heap_size && a[LEFT(i)] > a[i]) {        maxn = LEFT(i);     }    if (RIGHT(i) <= heap_size && a[RIGHT(i)] > a[maxn]) {        maxn = RIGHT(i);    }    if (maxn != i) {        swap(a[i], a[maxn]);            MaxHeapify(a, maxn, heap_size);    }}

程序第9行,如果我们一开始就是一个局部的最大堆,就满足第一个元素最大,我们是不会递归向下去维护堆的性质的

建堆:
a[(n/2)+1]到a[n-1]的元素是叶子节点;
对所有非叶子节点,调用一次MaxHeapify():

void BuildMaxHeap(int* a, int heap_size) {    for (int i = heap_size / 2; i >= 0; i--)        MaxHeapify(a, i, heap_size);}

复杂度:
这里直观理解的话,建一个最大堆貌似是O(nlog(n))
但是经过P88的运算就神奇变成了O(n)

堆排序:

void HeapSort(int* a, int heap_size) {    BuildMaxHeap(a, heap_size);    for (int i = heap_size; i > 1; i--) {        swap(a[1], a[i]);        heap_size--;        MaxHeapify(a, 1, heap_size);    }}

优先队列:

四种操作:

INSERT(S,x):把元素x插入到S中
MAXIMUM(S):返回S中具有最大键字的元素
EXTRACT-MAX(S):去掉并返回S中具有最大键字的元素
INCREASE-KEY(S,x,k):将元素x的关键字值增加到k, 这里假设k的值不小于x的原关键字值

MAXIMUM(S):

int HeapMaximum(int* a) {    return a[1];}

EXTRACT-MAX(S):

int HeapExtractMax(int* a, int heap_size) {    if (heap_size < 1) {        cout << "Heap Underflow\n";        return;    }    int maxn = a[1];    a[1] = a[heap_size];    heap_size --;    MaxHeapify(a, 1);    return maxn;}

INCREASE-KEY(S,x,k):

void HeapIncreaseKey(int* a, int i, int k) {    if (k < a[i]) {        cout << "Wrong Input\n";        return;    }    a[i] = k;    while(i > 1 && a[PARENT(i)] > a[i]) {        swap(a[i], a[PARENT(i)]);        i = PARENT(i);    }}

INSERT(S,x):
先开一个节点在优先队列的末尾,关键字赋为负无穷,然后将这个节点的关键字增加到x

void MaxHeapInsert(int* a, int x, int heap_size) {    heap_size = heap_size + 1;  //这里要保证不会溢出    a[heap_size] = -MAXN;    HeapIncreaseKey(a, heap_size, x);}
1 0