优先队列的基本数据结构(2)

摘要:本次提供另外一些优先队列的基本操作
【1】
对二叉堆进行下滤,就是让某个元素降至到使得它符合二叉堆优先结构的节点.

void PerLocateDown(Heap H,int i)
    //对二叉堆进行下滤
{
    int child;
    int FirstElement = H->Element[i];
    for(;i*2<= H->heapsize; i = child )
    {
        //for循环 一直到满足堆序或者到底层
       //获取最小儿子
        child = i*2;
    if (child != H->heapsize && H->Element[child+1]<H->Element[child] )
        child++;
    if(FirstElement > H->Element[child])
    {
        //不满足堆序,交换节点
        H->Element[i] = H->Element[child];
    }
    else
        break;//满足堆序
    }
    H->Element[i] = FirstElement;
}

【2】对二叉堆进行上滤,使得它上升到某个符合堆序的位置;

void PerLocateUp(Heap H,int i )
{
    //将一个元素【i】上滤
    int LastElement = H->Element[i];
    for(; LastElement < H->Element[i/2]; i /=2)
    {
        H->Element[i] = H->Element[i/2];
    }
    H->Element[i] = LastElement;
}

【3】
有很多时候,我们需要降低或者增加一个节点元素的值,那么降值之后,应该进行上滤.而升值之后,就应该进行下滤.

void DecreaseKey(int P,int delta,Heap H)
{
    if (delta < 0 )
        delta =  -1*delta;
    if(P<=H->heapsize)
    {
        H->Element[P] -= delta;
        PerLocateUp(H,P);
    }
    else
    {
        puts("the Position is too large");
        exit(1);
    }
}

【4】
最后是创建一个堆的操作.最容易想到的办法是连续进行N次插入操作(这样的操作有NlogN的时间界).但是我们可以思考,是否存在使得时间界是O(N)方法呢?实际上是有的。
{1}首先直接插入所有想要的数据,这将花费O(N)的时间。接着对倒数第二层开始的所有节点(N/2)进行下滤,可以证明所有比较的次数也将是O(N)。

Heap BuildHeap(int *A,int N)//将N个关键字放入H里
{
    Heap H = Initialize(N);
    H->heapsize = N;
    for(int i = 1;i <= N;i++)
        H->Element[i] = A[i-1];
    for(int j = N/2;j>=1; j --)
        PerLocateDown(H,j);
    return H;
}

[5]最后的一种操作则是进行删除一个固定的节点而不是最小的节点。所以先用Decreasekey将操作降到最小,然后用DeleteMin操作删除.

void Delete(int P,Heap H)
{
    int delta = H->Element[P] - H->Element[1] + 1;//delta使得key比H->Element[1]小
    DecreaseKey(P,delta,H);
    DeleteMin(H);
}

你可能感兴趣的:(优先队列的基本数据结构(2))