优先队列实现

先上测试:

#include<iostream>
#include<vector>
#include<queue>
#include<random>
#include<fstream>
#include"max_heap.h"
#include"boost/progress.hpp"


using namespace std;

fstream output("log.log" , fstream::out);

//生成1000个随机数,插入,
void test1(){
    boost::progress_timer t; //计算时间
    default_random_engine e;//生成随机数

    max_heap<int> m;
    for(int i = 0; i != 10000 ; ++i)
        m.push (e());

    //打印顶点的值,弹出顶点,循环直到空为止.
    while(!m.empty ()){
        output << m.top () << endl;//输出到文件,查看文件发现输出全部正确
        m.pop ();
    }
    cout << "max_heap:";
}


//std::priority_queue,与自己的实现性能对比
void test2(){
    boost::progress_timer t;
    default_random_engine e;

    priority_queue<int> q;
    for(int i = 0; i != 10000 ; ++i)
        q.push (e());
    while(!q.empty ()){
        output << q.top () << endl;
        q.pop ();
    }
    cout << "std::priority_queue:";


}

int main()
{
    test1();
    output << "\n========================\n";
    test2 ();
}


结果:

windows\linux:

由于使用了随机数,所以多测了几次,结果基本一致.居然比windows的实现快这么多,我不敢相信我的眼晴.于是去Linux下测试了一下,同一个代码,windows的居然差这么多.

结论:1.这次实现还是比较好的.2.windows的实现真的有传说中的那么差?


再测试一下使用string的性能(实现的大部份操作是通过简单的传值而不是引用),所以有必要测试一下传值的性能.

void test1(){
    boost::progress_timer t;
    uniform_int_distribution<int> u(0,26);
    default_random_engine e;

    max_heap<string> m;
    for(int i = 0; i != 10000 ; ++i){
        char buf[] = " ";
        buf[0] = 'a' + u(e);
        m.push (buf);

    }
    while(!m.empty ()){
        output << m.top () << endl;
        m.pop ();
    }
    cout << "max_heap:";
}

再上结果:

windows居然用了5秒,果然跟传闻一样,另外看来我的实现还是不错的,

头文件:

#ifndef MAX_HEAP_H
#define MAX_HEAP_H

#include<vector>

template<typename T>
class max_heap
{
public:
    max_heap();  
    T& top(); 
    void pop(); 
    void push(const T item);
    bool empty ();  
    int size();
private:
    std::vector<T> vector_;  //用vector实现

    int left(int pos);  //返回左儿子的索引
    int right(int pos); //右儿子索引
    int parent(int pos);  //父亲索引
    bool isleaf(int pos); //判断是否为叶结点
    void heapify(int pos); //使pos结点保持最大堆性质

    void build_heap(); //建堆
};


#include"max_heap.cpp"  //分离模版
#endif // MAX_HEAP_H

实现部分:

#ifndef HEAPCPP
#define HEAPCPP

#include"max_heap.h"

template<typename T>
max_heap<T>::max_heap(){ //默认构造函数
}

template<typename T>
bool max_heap<T>::empty (){
    return vector_.empty ();  
}

template<typename T>
T& max_heap<T>::top(){  
    return vector_.front ();
}

template<typename T>
int max_heap<T>::left(int pos){ 
    return 2*pos +1;
}

template<typename T>
int max_heap<T>::right (int pos){
    return 2*pos + 2;
}

template<typename T>
int max_heap<T>::parent (int pos){
    return (pos-1)/2;
}

template<typename T>
int max_heap<T>::size(){
    return vector_.size (); //元素个数
}

template<typename T>
bool max_heap<T>::isleaf(int pos){
    int n = size();
    return (n/2 <= pos) && (pos <= n-1);  //元素位于最底一层,并不能大于size-1,则为叶结点
}

template<typename T>
void max_heap<T>::heapify (int pos){
    if (isleaf (pos))
        return;  //叶结点,跳出

    int largestpos = pos; // 最大的索引
    int left_pos = left(pos); //左索引
    int right_pos = right(pos); //右索引

    //1.儿子的索引不能超过size - 1, 找出比较大的元素在哪里
    if (left_pos <= size()-1 && vector_[left_pos] > vector_[largestpos])
        largestpos = left_pos; 

    if (right_pos <= size()-1 && vector_[right_pos] > vector_[largestpos])
        largestpos = right_pos;

    //如果比较大的元素不是本结点,则要交换本结点的最大元素结点的值,对被交换的结点递归
    if (largestpos != pos){  
        auto temp = vector_[pos];
        vector_[pos] = vector_[largestpos];
        vector_[largestpos] = temp;

        heapify (largestpos);
    }

}

//建堆,从倒数第二层开始,往根结点推进
template<typename T>
void max_heap<T>::build_heap (){
    for (int pos = (size()-1)/2 ; pos >= 0 ; --pos)
        heapify (pos);
}

template<typename T>
void max_heap<T>::pop(){
    if (size() == 0) //没有元素,抛出异常
        throw std::runtime_error("out of range");

    //把最后一个元素调至第一位,删除最后一个元素,调用heapify使堆保持性质.
    vector_[0] = vector_[size() -1];
    vector_.pop_back ();
    
    heapify (0);

}

//在尾部插入值,然后迭代上升,找到适合的位置.
template<typename T>
void max_heap<T>::push (const T item){
    vector_.push_back (item);

    int currpos = size()-1;
    int parentops = parent (currpos);

    while (vector_[parentops] < vector_[currpos]){
        auto temp = vector_[currpos];
        vector_[currpos] =  vector_[parentops];
        vector_[parentops] = temp;

        currpos = parentops;
        parentops = parent (currpos);

        if (currpos == 0) //到顶部,结束
            break;

    }
}
#endif




实现没什么好说的.标准的二叉堆,另个,在头文件的尾部加一句#include"max_heap.cpp",能使模版的实现的定义分离


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值