最小堆实现最小优先队列

最小优先队列的可以实现的操作:
insert,插入一个元素
min,找到最小的元素
extract-min,去掉最小的元素并返回最小的元素
increase-key,增加一个关键字的值

优先队列的形式是一个堆。也就是有parent,left,right和自身的值的形式。实现他的操作是依赖于堆的操作,比如要插入一个key,实际上就是在堆中去找key的位置,然后维护堆。所以要时刻清醒的是现在的堆是一种什么形式,输出这个优先队列只是把堆按照数组的形式输出来了,本质上是在输出堆。


#include "stdafx.h"
#include<stdio.h>
#include <limits.h>


//最小堆实现最小优先序列

void swap(int *x, int *y)          //用作交换值的函数
{
    int t;
    t = *x;
    *x = *y;
    *y = t;

}

int parent(int i) //计算关系结点编号
{
    return i / 2;
}
int left(int i)
{
    return 2 * i;
}

int right(int i)
{
    return 2 * i + 1;
}

void minheap(int a[], int i,int truesize) //维护最xiao堆性质
{
    int smallest;  //储存最xiao结点编号
    int l;     //左结点
    int r;     //右 

    l = left(i);
    r = right(i);
    if (a[l - 1] < a[i - 1] && l <= truesize) //注意 C语言数组下标应该将i-1
        smallest = l;
    else
        smallest = i;
    if (a[r - 1] < a[smallest - 1] && r <= truesize)
        smallest = r;
    if (smallest != i)
    {
        swap(&a[smallest - 1], &a[i - 1]);               //逐层维hu        
        minheap(a, smallest,truesize);
    }
}

void buildminheap(int a[],int truesize)  //建立最xiao堆
{
    int n = truesize;
    int i;
    for (i = n / 2; i > 0; i--)
    {
        minheap(a, i,n);
    }
}

void heapsort(int a[],int truesize)  //堆排序,从大到小输出
{

    int i =truesize;
    for (; i>0; i--)
    {
        swap(&a[i - 1], &a[0]);
        truesize--;
        minheap(a, 1,truesize);
    }
}

int heap_min(int a[],int n)
{

    return a[0];
}

int heap_extract_min(int a[],int n)            
{


    if (n < 1)
        return 0;
    int min = a[0];
    a[0] = a[n - 1];
    n--;
    minheap(a,1,n);
    return min;

}

int  heap_increase_key(int a[], int i, int key)
{
    if (key > a[i])
    {                         //当key>parent 的时候终止
        return 0;
    }

    a[i] = key;
    while (i > 0 && a[parent(i)] > a[i])
    {
        swap(&a[i], &a[parent(i)]);
        i = parent(i);
    }

}

void min_heap_insert(int a[], int key,int n)
{
    n++;

    a[n - 1] = 100000;        //插入后的位置预置为正无穷
    heap_increase_key(a, n-1, key);
}




int main()
{
    int a[10] = { 4,1,3,2,16,9,10,14,8,7 };
    int  i,n=10;
    printf("\n堆中的元素是------------------\n");
    for (i = 0; i < n; i++) //输入堆中元素
        printf("%d   ", a[i]);

    printf("\n最小堆------------------\n");
    buildminheap(a,n);    //建立最xiao堆
    for (i = 0; i < n; i++)
        printf("%d ", a[i]);  //输出


/*  heapsort(a,n);       //堆排序
    printf("\nresult------------------\n");
    for (i = 0; i < n; i++)
        printf("%d ", a[i]);   //输出结果
*/

    heap_min( a,n);

    heap_extract_min(a,n);
    printf("\n调用extract后的最小堆:\n");
    for (i = 0; i < n-1; i++)
        printf("%d ", a[i]);   //输出结果
    printf("\n");


    min_heap_insert(a, 5, n-1);                //插入5

    printf("插入后的最小堆\n");
    for (i = 0; i < n; i++)
        printf("%d   ", a[i]);   //输出结果

    printf("\n插入后的堆排序\n");
    heapsort(a, n);
    for (i = 0; i < n; i++)
        printf("%d   ", a[i]);   //输出结果
        return 0;   
}

因为我一开始没有理解上面我所说的,队列的操作都是在操作堆,所以理解上出现了问题。在输出最小值的时候,我先用了heapsort进行堆排序然的
就觉得最小值应该是数组中的最后一个。把堆按sort输出了这样其实是没错的,但是到下面就出现问题了。extract_min一直是对一个最小堆在操作的,当你把你的最小堆sort成一个递减的数组的数组的时候,进行的操作是把堆顶元素与最后一个元素互换,然后把堆里的元素减少1,再把最后一个元素输出,最后一个元素即堆顶元素一定是当前的最小值,继续维护最小堆,重复这个过程。在这个过程中堆里的元素已经在减少了,最后堆已经没了。然后再去进行extract等一系列操作就不是在原来最小堆的基础上操作了。。。

猜你喜欢

转载自blog.csdn.net/alike_meng/article/details/82659787
今日推荐