• 最大堆+简单k路归并


    之前其实就写过堆排序了,这次主要想用class封装起来试一试,C++小白写得比较简陋,多担待。

    后面用最大堆模拟了一下k路归并,这是算法导论的一道思考题,经过别人的启发勉强实现了一下,感觉有想法就去做吧,别害怕啥,另外,看得懂的代码也不一定就真的敲得出来,还是要多code,不然就要被更多的人碾压了。

    k路归并我使用vector去实现的k个有序数组(降序),降序主要是懒得去改最大堆的代码(逃,最大元素出堆后,用该元素所在数组的下一个元素入堆,若为空,变为k-1路归并,这里我本来想着要用别的非空数组的未入堆元素代替,但其实实现起来有点小麻烦,而且也不必要这样做,任一时刻只要保证最大元素存在于最大堆就可以。废话有点多,下面是代码

    #include<iostream>
    #include<algorithm>
    #include<memory>//the hearder file of shared_ptr
    #include <vector>
    #include <list>
    #include <map>
    
    using namespace std;
    
    class pri_queue {
    public:
        void insert(int x);
        int maximum();
        int extract_max();//erase max and return it
        int increase_key(int x, int k);//将下标x的元素关键字值增加到k,假设k>x,返回新下标(从1开始
        pri_queue() {};
        pri_queue(initializer_list<int> il);
    private:
        bool empty() { return data.empty(); }
        void build_heap();
        void max_heapify(int i);
        vector<int> data;
    };
    
    void pri_queue::max_heapify(int i) {
        int lch = i * 2, rch = i * 2 + 1;
        int largest = i;
        if (lch <= data.size() && data[lch - 1] > data[largest - 1]) 
            largest = lch;
        if (rch <= data.size() && data[rch - 1] > data[largest - 1])
            largest = rch;
        if (i == largest)return;
    
        swap(data[largest - 1], data[i - 1]);
        max_heapify(largest);
    }
    
    void pri_queue::build_heap() {
        for (int n = data.size() / 2;n > 0;n--)
            max_heapify(n);
    }
    
    int pri_queue::maximum() {
        return data[0];
    }
    
    int pri_queue::extract_max() {
        if (empty()) {//简单的测试
            cerr << "this priority is empty!!!" << endl;
            return 233;
        }
        int ret = data[0];
        data[0] = data[data.size() - 1];
        data.erase(data.end() - 1);
        max_heapify(1);
    
        return ret;
    }
    
    pri_queue::pri_queue(initializer_list<int> il) :data(il) {
        build_heap();
    }
    
    void pri_queue::insert(int x) {
        data.push_back(-10000000);//姑且看为-INF
        increase_key(data.size(), x);
    }
    
    int pri_queue::increase_key(int x, int k) {
        if (x <= 0)cerr << "underflow!!" << endl;
        if (data[x - 1] > k)cerr << "k is too small!!" << endl;
    
        //data[x - 1] = k;
        for (;x / 2 > 0 && data[x / 2 - 1] < k;x /= 2)
            data[x - 1] = data[x / 2 - 1];
        data[x - 1] = k;
    
        return x;
    }
    
    void print(const vector<int>& a) {
        for (const auto& mem : a)cout << mem << " ";
        cout << endl;
    }
    
    int main(void) {//模拟k路归并
        vector<int > l1 = { 5,3,1 };
        vector<int> l2 = { 16,8,0 };
        vector<int> l3 = { 64,32,4 };
    
        map<int, vector<int> * > k2id;//关键字到对应链表的映射
    
        for (int i = l1.size();i > 0;i--)k2id[l1[i - 1]] = &l1;
        for (int i = l2.size();i > 0;i--)k2id[l2[i - 1]] = &l2;
        for (int i = l3.size();i > 0;i--)k2id[l3[i - 1]] = &l3;
    
        pri_queue pq({ l1[0],l2[0],l3[0] });
        int cur = pq.extract_max();
        cout << cur << " ";
        vector<int> *test = k2id[cur];
        test->erase(test->begin());
    
        //cout << l1.empty() << endl;
        while (1) {
            if (l1.empty() && l2.empty() && l3.empty())break;
            if(!test->empty())//如果一路为空,则变为(k-1)路归并
                pq.insert((*test)[0]);
            cur = pq.extract_max();
            test = k2id[cur];
            cout << cur << " ";
            test->erase(test->begin());
        }
        
        
    
        return 0;
    }

     

  • 相关阅读:
    JAVA中分为基本数据类型及引用数据类型
    Tomcat部署HTTPS协议
    MySQL SQL 数据排名查询某条数据是总数据的第几条
    Myeclipse或Eclipse 老是出现JPA project Change Event Handler
    初识Go
    MyBatis xml文件中的大于、小于等符号写法
    jQuery实现5秒倒计时
    JS时间处理由CST格式转成GMT格式时间
    HTML新增加的属性和废除的属性
    HTML 锚点
  • 原文地址:https://www.cnblogs.com/schsb/p/8555471.html
Copyright © 2020-2023  润新知