堆(优先队列)的基本操作

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

堆(优先队列)的基本操作

堆是一棵完全二叉树,所以可以利用数组来实现。

以1号作为root,则对于数组中的任意一个i,其左儿子在(2*i),右儿子在(2*i+1),父亲在(i/2)。

下面以最小堆为例,实现一些基本操作:

1.堆的声明

#define INF 0x3f3f3f3f
#define MAX 1005

int heap[MAX];
heap[0] = -INF;
int Size = 0;

2.两个基本的操作:PercolateUp,PercolateDown

//比较父节点与子节点,若父节点大,则交换,实现子节点的上滤

void PercolateUp(int p){
    while(p/2){
        if(heap[p] < heap[p/2]){
            swap(heap[p], heap[p/2]);
            p /= 2; //更新p
        }
        else  break;

    }
}


//将左右两个儿子节点与父节点比较,若父节点大,下滤(与儿子节点交换)

void PercolateDown(int p){
    int len = Size;
    while(p*2 <= len){
        if(heap[p*2] < heap[p]){    //左儿子
            swap(heap[p], heap[p*2]);
            p *= 2;
        }
        else if(heap[p*2 + 1] < heap[p]){   //右儿子
            swap(heap[p], heap[p*2 + 1]);
            p = (p*2)+1;
        }
        else return;
    }
}

3.Insert

将元素先插入到末尾的下一个位置(保证为完全树),然后逐层上滤,寻找正确的位置。
每一次上滤都需要反复交换,但是纵观整个过程,会发现每一步只需要将不满足条件的父亲下移,当找到正确的位置之后,再进行一步交换即可。
如果插入的元素是整个堆的最小值,则X会被一直推到堆顶。此时X大于heap[0](-INF),循环终止,交换。


void Insert(int x){

    if(Size == MAX - 1){
        cout<<"FULL"<<endl;
        return;
    }
    int i;
    //将x置于最后,然后向上调整(与他爹比较)
    for(i = ++Size; data[i / 2] > x; i/=2)
       data[i] = data[i/2];

    data[i] = x;
}

4.DeleteMin

//删除堆顶的最小元,之后将最后一个节点放到1号位置,然后PercolateDown,进行调整,保持完全树


int DeleteMin(){
    int i, child;
    if(Size == 0){
        cout<<"Empty"<<endl;
        return ERROR;
    }
    int MinElem = heap[1];
    int LastElem = heap[Size--];    

    for(i = 1; i*2 < Size; i = child){
        child = i*2;
        //找相对较小的儿子节点
        if(child != Size && heap[child + 1] < heap[child])
            child++;
        //percolate one level
        if(Last > heap[child])
            heap[i] = heap[child];
        else    break;
    }

    heap[i] = LastElem;
    return MinElem;
}
 
 
 
 
 

猜你喜欢

转载自blog.csdn.net/ParadiseHeaven/article/details/78805794