最大堆+简单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;
}

 

原文地址:https://www.cnblogs.com/schsb/p/8555471.html