索引优先队列

索引优先队列

上篇讲述了优先队列,一种能够快速访问最大元素或最小元素的数据结构,但是考虑这样一种情况,公司按姓名录入员工信息,并按照薪水加入了优先队列,某员工薪水需要更改,假设薪水排名为n,那么我们需要怎样操作呢?首先将前n名员工出列,然后改正第n名薪水,最后将这n名员工入列,操作太复杂,不符合程序员追求性能(懒)的特性,于是想到将优先队列的元素加一个索引,可以随机访问.这种加入索引的优先队列就叫做索引优先队列.

用c++构造索引优先队列如下:

类构造

class IndexPriorQueue{
private:
    int index;//the num of items
    int size;//capacity
    int* pq;//index binaryheap
    int* qp;//qp[pq[i]]=pq[qp[i]]=i
    T* item;//item array;
public:
    IndexPriorQueue(int qsize){//constructor function
        size=qsize;
        index=0;
        pq=new int[size+1];
        qp=new int[size+1];
        item=new T[size+1];
        for(int i=0;i<size+1;i++)
            qp[i]=-1;

    }
    void insert(int k,T v){
        if(contain(k)){
            cout<<"index is already in queue"<<endl;
            return;
        }
        //cout<<"insert"<<endl;
        item[k]=v;
        pq[++index]=k;
        qp[k]=index;
        swim(index);
    }
    bool contain(int k){
        return qp[k]!=-1?1:0;
    }
    void deleteat(int k){
        int j=qp[k];
        pq[j]=pq[index];
        index--;
        swim(j);
        sink(j);
        qp[k]=-1;
    }
    T delmax(){
        int k=pq[1];
        T max=item[pq[1]];
        pq[1]=pq[index--];
        sink(1);
        qp[k]=-1;
        return max;
    }
    void swim(int j){
        while(j>1){
            if(less(j/2,j)){
                exch(j/2,j);
                j=j/2;
            }else{
                break;
            }
        }
    }
    void sink(int j){

        while(2*j<=index){
            int k=2*j;
            if(k<index&&less(k,k+1))
                k++;
            if(less(j,k))
                exch(j,k);
            else
                break;
            j=k;
        }
    }
    bool less(int i,int j)
    {
        return item[pq[i]]<item[pq[j]]?1:0;
    }
    void exch(int m,int n){
        int temp=pq[m];
        pq[m]=pq[n];
        pq[n]=temp;
        qp[pq[m]]=m;
        qp[pq[n]]=n;
    }
    void display(){
        cout<<"item:";
        for(int i=1;i<size+1;i++){
            cout<<item[i]<<"  ";
        }
        cout<<endl;
        cout<<"pq:";
        for(int i=1;i<size+1;i++){
            cout<<pq[i]<<"  ";
        }
        cout<<endl;
        cout<<"qp:";
        for(int i=1;i<size+1;i++){
            cout<<qp[i]<<"  ";
        }
        cout<<endl;

    }
};

其中,每次插入值时,构造堆比较的是元素值的大小,然后索引会标记元素值,这样可以通过索引非常方便的访问元素.

测试代码

int main(){
    cout<<"before insert:"<<endl;
    IndexPriorQueue<char> ipq(10);
    ipq.display();
    ipq.insert(1,'a');
    ipq.insert(2,'d');
    ipq.insert(3,'c');
    ipq.insert(5,'z');
    ipq.insert(6,'x');
    cout<<"after insert:"<<endl;
    ipq.display();
    cout<<"delmax:";
    cout<<ipq.delmax()<<endl;;
    ipq.display();
    ipq.insert(5,'y');
    ipq.display();
    ipq.deleteat(6);
    cout<<"deleteat";
    ipq.display();
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值