堆排序——基本概念及基本实现代码

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hh66__66hh/article/details/82850300

堆排序——基本概念及基本实现代码

堆的基本概念

(二叉)堆是一个数组,它可以被看成一个近似的完全二叉树,树上每个节点对应数组里的一个元素。除了最底层外,该树是完全充满的,且是从左向右填充的。
假设A是表示堆的数组,则A包含两个属性:
(1)A.length : 数组的元素个数;
(2)A.heap_size : 数组中有多少个元素用来存储堆里的元素。
这里,A.heap_size <= A.length.
二叉堆的根结点是A[1],对于一个给定的下标i(i>1),其父节点、左孩子节点、右孩子节点的下标为:
PARENT(i) = i / 2;
LEFT(i) = i2;
RIGHT(i) = i
2 + 1.
例如下图,下标为5的节点,其父节点下标为5 / 2 = 2,其左孩子节点下标为5*2 = 10. 在这里插入图片描述

堆通常可以分为最小堆和最大堆:
(1)最大堆:除了根节点外,其余节点满足:A[PARENT(i)] >= A[i].
简单来说,就是该堆里的每个节点,其父节点一定大于或等于它的值,该堆的最大元素放在了根节点中。
(1)最小堆:除了根节点外,其余节点满足:A[PARENT(i)] <= A[i].
简单来说,就是该堆里的每个节点,其父节点一定小于或等于它的值,该堆的最小元素放在了根节点中。

堆的几个实现函数

1.维护堆的性质

MAX_HEAPIFY : 输入一个表示堆的数组A和一个下标,假定根节点为LEFT(i)和RIGHT(i)的二叉树都是最大堆,这时A[i]可能小于它的孩子,则通过该函数来维护最大堆。

void MAX_HEAPLFY(int* A, int i) {
    int l, r, m, temp;
    l = 2*i;
    r = 2*i +1;
    m = i;
    temp = A[i];
    if(l<=heap_size && A[i]<A[l]) {
        temp = A[l];
        m = l;
    }
    if(r<=heap_size && A[r]>A[m]) {
        temp = A[r];
        m = r;
    }
    if(m!=i) {
        A[m] = A[i];
        A[i] = temp;
        MAX_HEAPLFY(A, m);
    }

}

2.建堆

BULD_MAX_HEAP:输入一个数组A,将该数组转换为一个最大堆

void BULD_MAX_HEAP(int* A, int length) {
    heap_size = length;
    int i;
    for(i = heap_size/2; i>0; i--) {
        MAX_HEAPLFY(A, i);
    }
}

3.堆排序算法

HEAPSORT: 输入一个数组A,并对其进行基于堆的排序

    BULD_MAX_HEAP(A, length);
    int temp, i;
    for(i=length; i>1; i--) {
        temp = A[1];
        A[1] = A[i];
        A[i] = temp;
        heap_size--;
        MAX_HEAPLFY(A, 1);
    }
}

优先队列

优先队列是一种用来维护有一组元素构成的集合S的数据结构,其中每个元素都有一个关键字(key)。一个最大优先队列支持以下操作:
INSERT(S, x) : 把元素插入集合S中;
HEAP_MAXIMUM(S):返回S中关键字最大的元素;
EXTRACT_MAX(S):去掉并返回S中具有最大关键字的元素;
INCREASE_KEY(S, id, add_value):将下标为id的元素的关键字加上add_value,并调整S,让其仍是一个最大优先队列。

HEAP_MAXIMUM(S)

int HEAP_MAXIMUM(int* A) {
    return A[1];
}

EXTRACT_MAX(A)

int EXTRACT_MAX(int* A) {
    //if(heap_size<1)
    int m, i;
    m = A[1];
    A[1] = A[heap_size];
    heap_size--;
    MAX_HEAPLFY(A, 1);
    return m;
}

INCREASE_KEY(S, id, add_value)

void INCREASE_KEY(int* A, int i, int add_number) {
    A[i] = A[i] + add_number;
    int parent, temp;
    while(i>1) {
        parent = i/2;
        if(A[parent] > A[i]) {
            break;
        }
        temp = A[parent];
        A[parent] = A[i];
        A[i] = temp;
        i = parent;
    }
}

猜你喜欢

转载自blog.csdn.net/hh66__66hh/article/details/82850300