算法导论的C实现——优先队列


堆排序的平均效率虽然小于快排,但是堆排序仍然有很多应用。堆排序的典型应用就是作为作业的调度系统,系统运行过程中可以随时INSERT一个新的任务。linux内核中的 sort函数也是用的堆排序:

作者:知乎用户
链接:https://www.zhihu.com/question/20842649/answer/70922215
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

/**
 * sort - sort an array of elements
 * @base: pointer to data to sort
 * @num: number of elements
 * @size: size of each element
 * @cmp_func: pointer to comparison function
 * @swap_func: pointer to swap function or NULL
 *
 * This function does a heapsort on the given array. You may provide a
 * swap_func function optimized to your element type.
 *
 * Sorting time is O(n log n) both on average and worst-case. While
 * qsort is about 20% faster on average, it suffers from exploitable
 * O(n*n) worst-case behavior and extra memory requirements that make
 * it less suitable for kernel use.
 */

优先队列(Priority Queue)则是堆排序的另一种应用。
在这里插入图片描述下面介绍一下优先队列操作的实现。

MAXIMUM

原理

最大值的原理很简单,就是返回根结点的 k e y key key
MAXIMUM

return A[1]

代码实现

//HEAP_MAXIMUM
int HEAP_MAXIMUM(HEAP *A)
{
    return A->Array[0];
}

EXTRACT-MAX

原理

最大值提取的意思是将二叉堆中的最大元素提取出来,此时二叉堆长度将减少,并且剩下的二叉堆将维持最大堆的性质。
EXTRACT-MAX

swap(A[1], A[A.heap-size])
A.heap-size-1
MAX-HEAPIFY(A, 1)
return A[A.heap-size+1]

代码实现

//HEAP_EXTRACT_MAXIMUM
int HEAP_EXTRACT_MAXIMUM(HEAP *A)
{
    if(A->heap_size<0)
    {
        ERROR("heap underfloor");
    }
    else
    {
        SWAP(&A->Array[0], &A->Array[A->array_size-1]);
        A->heap_size--;
        MAX_HEAPIFY(A, 0);
        return A->Array[A->array_size-1];
    }
}

INCREASE

原理

增大键值函数可以将二叉堆中某一结点键值增大,同时还要维持最大堆的性质。因为是在最大堆的基础上进行的,所以只需要关注改变的结点和其父节点就可以了。
INCREASE(A, i, key)

if key<A[i]
	ERROR("new value is smaller than before one")
else 
A[i] = key
while i>1 and A[i]>A[PARENT(i)]
	swap(A[i], A[PARENT(i)])
	i = PARENT(i)

代码实现

//HEAP_INCREASE_KEY
void HEAP_INCREASE_KEY(HEAP *A, uint32_t i, int key)
{
    if(key < A->Array[i-1])
    {
        ERROR("new key is smaller than the current one");
    }
    else
    {
        A->Array[i-1] = key;
        while(i>1 && A->Array[PARENT(i)-1]<key)
        {
            SWAP(&A->Array[i-1], &A->Array[PARENT(i)-1]);
            i=PARENT(i);

        }
    }
}

在头文件中定义一个ERROR函数用以实现错误信息的输出:

#define ERROR(s) printf("!!!ERROR:%s!!!\n", s)

INSERT

原理

插入是先插入 − ∞ -\infty ,然后再将其增大的想要的键值。之所以这样做,是为了少执行一遍建堆的过程,而只INCREASE即可。
INSERT(A, key)

A.heap-size += 1
A[heap-size] = -inf
INCREASE(A, heap-size, key)

代码实现

//MAX_HEAP_INSERT
void MAX_HEAP_INSERT(HEAP *A, int key)
{
    A->heap_size++;
    A->Array[A->heap_size-1] = negINFINITY;
    HEAP_INCREASE_KEY(A, A->heap_size, key);
}

DELETE

原理

删除元素时要注意二叉堆的长度要对应减少。
DELETE(A, i)

swap(A[i], A[A.heap-size])
A.heap-size -= 1
BUILD-MAX-HEAPIFY(A)

代码实现

//6.5-8
//MAX_HEAP_DELETE
void MAX_HEAP_DELETE(HEAP *A, uint32_t i)
{
    SWAP(&A->Array[i-1], &A->Array[A->heap_size-1]);
    A->heap_size--;
    BUILD_MAX_HEAP(A);
}

测试函数

以上功能的测试函数我把它们放到一起了:

//------------------------- priority queue -------------------------//
//TEST FUNCTION
void testPriorityQueue()
{
    //6.5-1
    int testArray[12] = {15, 13, 9, 5, 12, 8, 7, 4, 0, 6, 25, 100};
    uint32_t array_size = 12;
    HEAP A = {12, array_size, testArray};

    //bulid max heap
    BUILD_MAX_HEAP(&A);
    drawBINTREE(A.Array, A.heap_size);
    //maximum
    printf("the maximum value of heap is %d\n", HEAP_MAXIMUM(&A));
    //extract maximum
    HEAP_EXTRACT_MAXIMUM(&A);
    HEAP_EXTRACT_MAXIMUM(&A);
    printf("bintree after extract:\n");
    drawBINTREE(A.Array, A.heap_size);
    //increase key
    HEAP_INCREASE_KEY(&A, 7, 10);
    printf("bintree after increase:\n");
    drawBINTREE(A.Array, A.heap_size);
    //insert key
    MAX_HEAP_INSERT(&A, 11);
    printf("bintree after insert:\n");
    drawBINTREE(A.Array, A.heap_size);
    //6.5-8
    //delete element
    MAX_HEAP_DELETE(&A, 2);
    printf("bintree after delete:\n");
    drawBINTREE(A.Array, A.heap_size);
}

得到的结果如下:

The height of this tree is: 4
                            100
            25                              15
    5               13              9               7
4       0        6       12      8
the maximum value of heap is 100
bintree after extract:
The height of this tree is: 4
                            100
            13                              15
    5               12              9               7
4       0        6
bintree after increase:
The height of this tree is: 4
                            100
            13                              15
    5               12              9               10
4       0        6
bintree after insert:
The height of this tree is: 4
                            100
            13                              15
    5               12              9               10
4       0        6       11
bintree after delete:
The height of this tree is: 4
                            100
            12                              15
    5               11              9               10
4       0        6
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值