堆——最小优先队列以及实现

本文介绍了如何使用堆数据结构实现最大/最小优先队列,特别是最小优先队列的C++实现。代码展示了插入、获取最小关键字、删除最小元素和降低关键字等操作,用于作业调度等场景。示例代码详细解释了各个方法的实现原理,如调整堆的过程。
摘要由CSDN通过智能技术生成
  1. 数据结构堆的介绍:堆与堆排序

  2. 用于作业调度的最大/小优先队列可以使用堆来实现:

    • 最大优先队列支持以下操作
    ○ INSERT(S, x):把元素x插入集合S
    ○ MAXIMUM(S):返回S中具有最大关键字的元素
    ○ EXTRACT-MAX(S):去掉并返回S中的具有最大键字的元素
    ○ INCERASE-KEY(S, x, k):将元素x的关键字值增加到k,这里假设k的值不小于x的原关键字值

    • 最小优先队列支持以下操作:
    ○ INSERT
    ○ MINIMUM
    ○ EXTRACT_MIN
    ○ DECREASE_KEY

  3. 最小优先队列的C++实现:

    class MinHeapFirstQueue
    {
    public:
        MinHeapFirstQueue() {};
        ~MinHeapFirstQueue() {};
        void insert(int id); //插入元素
        int minimum(); //返回最小关键字的元素
        int extract_min(); //去掉并返回最小关键字的元素
        void decrease_key(int id, int k); //把元素id的关键字减少到k,k不小于原关键字
    
    private:
       int parent_(int idx);
        int left_(int idx);
        int right_(int idx);
    
        bool shit_down_(int id, int size); //降级,不能降级返回false
        void shit_up_(int id);
        void swap_(int id1, int id2);
        void del_(int id);
    
        std::vector<int> keys_;
        std::unordered_map<int, int> dx_map_; //id-idx map
        std::unordered_map<int, int> xd_map_; //idx-id map
    
    };
    
    void MinHeapFirstQueue::insert(int id)
    {
        if(id < 0)
        {
            return;
        }
    
        if(dx_map_.count(id) == 0) //插入新的元素
        {
            cout << "new node" << endl;
            dx_map_[id] = keys_.size();
            xd_map_[keys_.size()] = id;
            keys_.push_back(0); //初始的关键值设为0
            shit_up_(id);
        }
        else
        {
            cout << "insert existing node" << endl;
            keys_[dx_map_[id]] = 0;
            if(!shit_down_(id, keys_.size()))
            {
                shit_up_(id);
            }
        }
    
        return ;
    }
    
    int MinHeapFirstQueue::minimum()
    {
        if(keys_.empty())
        {
            cout << "队列为空!" << endl;
            return (1 << 30) - 1;
        }
    
        return keys_[0];
    }
    
    int MinHeapFirstQueue::extract_min()
    {
        int ret = 0;
    
        if(keys_.empty())
        {
            cout << "extract_min: 优先队列为空!" << endl;
            return -1;
        }
    
        ret = keys_[0];
        del_(xd_map_[0]);
        return ret;
    
    }
    
    void MinHeapFirstQueue::decrease_key(int id, int k)
    {
        if(dx_map_.count(id) == 0)
        {
            return ;
        }
    
        if(keys_[dx_map_[id]] < k)
        {
            return ;
        }
        keys_[dx_map_[id]] = k;
        shit_up_(id);
    }
    
    inline int MinHeapFirstQueue::parent_(int idx)
    {
        return (idx - 1) / 2;
    }
    
    inline int MinHeapFirstQueue::left_(int idx)
    {
        return 2 * idx + 1;
    }
    
    inline int MinHeapFirstQueue::right_(int idx)
    {
        return 2 * idx + 2;
    }
    
    bool MinHeapFirstQueue::shit_down_(int id, int size)
    {
        int i = dx_map_[id];
        int j = left_(i);
        while(j < size) //迭代实现
        {
            if(right_(i) < size && keys_[right_(i)] < keys_[j])
            {
                j = right_(i);
            }
            if(keys_[i] < keys_[j])
            {
                break;
            }
            swap_(xd_map_[i], xd_map_[j]);
            i = j;
            j = left_(i);
        }
    
        return dx_map_[id] > xd_map_[i];
    }
    
    void MinHeapFirstQueue::shit_up_(int id)
    {
        int i = dx_map_[id];
        int j = parent_(i);
    
        if(i == 0)
        {
            cout << "shit_up: root node" << endl;
            return;
        }
        cout << "shitup: j: " << j << endl;
        while(j >= 0)
        {
            if(keys_[i] > keys_[j])
            {
                break;
            }
            swap_(xd_map_[i], xd_map_[j]);
            i = j;
            if(i == 0)
            {
                cout << "shit_up: root node" << endl;
                return;
            }
            j = parent_(i);
        }
    }
    
    void MinHeapFirstQueue::swap_(int id1, int id2)
    {
        int idx1 = 0;
        int idx2 = 0;
        
        if(dx_map_.count(id1) == 0 || dx_map_.count(id2) == 0)
        {
            return ;
        }
    
        idx1 = dx_map_[id1];
        idx2 = dx_map_[id2];
    
        std::swap(keys_[idx1], keys_[idx2]);
        dx_map_[id1] = idx2;
        dx_map_[id2] = idx1;
        xd_map_[idx1] = id2;
        xd_map_[idx2] = id1;
    }
    
    void MinHeapFirstQueue::del_(int id)
    {
        int i = 0;
        int j = 0;
        if(dx_map_.count(id) == 0)
        {
            return ;
        }
    
        i = dx_map_[id];
        j = keys_.size() - 1;
        if(i < j) //非队尾元素
        {
            swap_(xd_map_[i], xd_map_[j]); //把删除的元素移到队尾
            if(!shit_down_(xd_map_[i], keys_.size()-1)) //维护堆的性质
            {
                shit_up_(xd_map_[i]);
            }
        }
        dx_map_.erase(xd_map_[j]);
        xd_map_.erase(j);
        keys_.pop_back();
    }
    
    int main()
    {
        MinHeapFirstQueue fq;
        fq.insert(0);
        fq.insert(1);
        fq.insert(2);
        fq.decrease_key(0, -1);
        cout << fq.minimum() << endl;
        fq.decrease_key(1, -2);
        cout << fq.minimum() << endl;
        fq.decrease_key(2, -3);
        cout << fq.minimum() << endl;
        
        cout << fq.extract_min() << endl;
        cout << fq.minimum() << endl;
        cout << fq.extract_min() << endl;
        cout << fq.minimum() << endl;
        cout << fq.extract_min() << endl;
        cout << fq.minimum() << endl;
        return 0;
    }```
    
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值