Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么是c++;使用自定义比较函子时,stl优先级_队列的执行效率不如预期_C++_Stl_Set_Priority Queue - Fatal编程技术网

C++ 为什么是c++;使用自定义比较函子时,stl优先级_队列的执行效率不如预期

C++ 为什么是c++;使用自定义比较函子时,stl优先级_队列的执行效率不如预期,c++,stl,set,priority-queue,C++,Stl,Set,Priority Queue,当我使用定制的比较函数类创建stl优先级_队列时,我发现它的性能非常差(推送元素的复杂性似乎是O(n)而不是O(logN))。但我测试使用具有相同比较函数的stl集,该集的运行速度比优先级队列快得多。为什么会这样 //There are a lot of horizontal lines on x-axis. Each line is represeted by a pair<int,int> p, //where p.first is the left point

当我使用定制的比较函数类创建stl优先级_队列时,我发现它的性能非常差(推送元素的复杂性似乎是O(n)而不是O(logN))。但我测试使用具有相同比较函数的stl集,该集的运行速度比优先级队列快得多。为什么会这样

    //There are a lot of horizontal lines on x-axis. Each line is represeted by a pair<int,int> p, 
    //where p.first is the left point and p.second is the right point. 
    //For example, p(3,6) is a line with end points of 3 and 6.
    //a vector<pair<int,int>> lines represents all these lines.
    //
    //I would like to scan all the end points from left to right alone x-axis. 
    //I choose to use a struct end_point to represent each end point,
    //     struct end_point{
    //          int x_coor;  //the x coordinate of the end point;  
    //          int index;   //the index of the line, this end point belongs to, in vector lines.
    //     };

    //For example, if there are 3 lines on x-axis line1(1,10), line2(2,9) and line3(3,8), 
    //the vector of lines looks like vector<pair<int,int>> lines = [(1,10), (2,9), (3,8)];
    //And the 6 end points look like {1,0}, {10,0}, {2,1}, {9,1}, {3,2}, {8,2}
    //I want to sort these end points by comparing their x_coor(if equal, use index to identify different lines).

    //If I choose a priority_queue to sort them, it has a very poor performace(6000 μs to complete 1000 lines).
    //But I do the same thing(by using the same customized compare function class) on a set, 
    //it runs much faster(just 246 μs) than priority_queue.
    //
    //My question:
    //1.Why priority_queue perform so bad as to set in this example?
    //2.For the comparator function class, I introduce a variable count to record how many times the compare function is called totally.
    //but for priority_queue, it seems that each compare function would resume it to 0 without keeping it, while for the set, it could 
    //increase all the time as I expect. Is there any bug in my code(or that is the reason why there performed so differently)?

    //

    #include <iostream>
    #include <queue>
    #include <set>
    #include <chrono>

    using namespace std::chrono;


    //generate 1000 lines of [(0, 10000), (1, 9999), (2,9998),(3,9997).....(999, 9001)]
    std::vector<std::pair<int,int>> linesGenerator(){
        std::vector<std::pair<int,int>> lines;
        int lines_num = 1000;
        int length_range = 10000;

        for(int i = 0; i < lines_num; i++){
            int start = i;
            int end = length_range - i;

            lines.push_back(std::make_pair(start, end));
        }

        return lines;
    }

    struct end_point{
        int x_coor;  //the x coordinate of the end point;  
        int index;   //the index of the line, this end point belongs to, in vector lines.

        end_point(int x, int i):x_coor(x), index(i){}
    };

    //customized compare function class for priority_queue
    class pqCompare{
    public:
        //construct by keeping its own copy of lines.
        pqCompare(std::vector<std::pair<int,int>> &_lines){
            lines = _lines;
            count = 0; //use for count how many times the compare operation is called.
        }

        bool operator()(end_point ep1, end_point ep2){
            ++count; //increase by 1 if this function is called once.

            //std::cout<<"count:"<<count<<std::endl;

            if(ep1.x_coor != ep2.x_coor){
                return ep2.x_coor < ep1.x_coor;
            }

            return ep1.index > ep2.index;
        }


    private:
        std::vector<std::pair<int,int>> lines; 
        int count;
    };

    //customized compare function for set, almost same as priority_queue,
    //the difference is only because piroity_queue is a max_heap.
    class setCompare{
    public:
        setCompare(std::vector<std::pair<int,int>> &_lines){
            lines = _lines;
            count = 0;
        }

        bool operator()(end_point ep1, end_point ep2){
            ++count;

            //std::cout<<"count:"<<count<<std::endl;

            if(ep1.x_coor != ep2.x_coor){
                return ep1.x_coor < ep2.x_coor;
            }

            return ep1.index < ep2.index;
        }


    private:
        std::vector<std::pair<int,int>> lines;
        int count;
    };

    void test_pqueue()
    {
        //generate 1000 lines;  
        std::vector<std::pair<int,int>> lines = linesGenerator();

        //create a priority_queue with cmp as comparator.
        pqCompare cmp(lines);
        std::priority_queue<end_point, std::vector<end_point>, pqCompare> ct(cmp);

        auto tp0 = steady_clock::now();
        for (int i = 0; i < lines.size(); ++i){
            //for each line, there are 2 end points.
            int left_point = lines[i].first;
            int right_point = lines[i].second;

            ct.push(end_point(left_point, i));
            ct.push(end_point(right_point, i));
        }
        //std::cout<<"total count"<<cmp.getCount()<<"\n";
        auto tp1 = steady_clock::now();

        std::cout << __PRETTY_FUNCTION__ << ':' << duration_cast<microseconds>(tp1-tp0).count() << " μs\n";
    }


    void test_set()
    {

        std::vector<std::pair<int,int>> lines = linesGenerator();
        setCompare cmp(lines);

        std::set<end_point, setCompare> ct(cmp);
        auto tp0 = steady_clock::now();

        for (int i = 0; i < lines.size(); ++i){
            int left_point = lines[i].first;
            int right_point = lines[i].second;

            ct.insert(end_point(left_point, i));
            ct.insert(end_point(right_point, i));
        }
        auto tp1 = steady_clock::now();

        std::cout << __PRETTY_FUNCTION__ << ':' << duration_cast<microseconds>(tp1-tp0).count() << " μs\n";
    }


    int main()
    {
        test_pqueue();
        test_set();
    }
//x轴上有很多水平线。每条线由一对p表示,
//其中p.first是左点,p.second是右点。
//例如,p(3,6)是端点为3和6的直线。
//矢量线表示所有这些线。
//
//我想从左到右扫描x轴上的所有端点。
//我选择使用结构端点来表示每个端点,
//结构端点{
//int x_coor;//端点的x坐标;
//int index;//此端点所属直线的索引,以矢量线表示。
//     };
//例如,如果x轴上有3条线,即线1(1,10)、线2(2,9)和线3(3,8),
//线的向量看起来像向量线=[(1,10),(2,9),(3,8)];
//6个端点看起来像{1,0},{10,0},{2,1},{9,1},{3,2},{8,2}
//我想通过比较它们的x_coor对这些端点进行排序(如果相等,则使用索引来标识不同的线)。
//如果我选择一个优先级队列对它们进行排序,它的性能非常差(6000μs完成1000行)。
//但是我在一个集合上做同样的事情(通过使用相同的定制比较函数类),
//它的运行速度比优先级队列快得多(仅246μs)。
//
//我的问题:
//1.为什么优先级队列的性能如此糟糕,以至于在本例中设置了优先级?
//2.对于comparator函数类,我引入了一个变量计数来记录compare函数总共被调用了多少次。
//但对于priority_队列,似乎每个compare函数都会将其恢复为0,而不会保留它,而对于set,它可以
//如我所料,一直在增加。我的代码中是否存在任何bug(或者这就是为什么它们的执行方式如此不同的原因)?
//
#包括
#包括
#包括
#包括
使用名称空间std::chrono;
//生成1000行[(0,10000),(1,9999),(29998),(39997)…(999,9001)]
std::vector linesGenerator(){
std::矢量线;
int line_num=1000;
整数长度_范围=10000;
对于(int i=0;i//std::coutFyi
for(int i=0;i<10000,i++)
不是有效的for循环。也许可以发布一个真实的最小、完整、可验证的示例来重现您的问题。我不确定您使用什么来比较您的运行时,但优先级队列应该仅在缓存管理方面获胜。请用一个完整的示例来更新您的问题,如生成结果的链接示例,我包括你用来衡量结论的任何机制和方法。我为我的问题提供了一个例子。我认为现在应该更清楚了。你能帮我吗?为什么你需要在比较运算符中使用一份
?你没有使用它。如果你需要在比较运算符中使用大量数据,请保留一个ref引用它。比较运算符不应该是重量级的。在两个比较运算符中都将其更改为const reference可以解决性能问题。
void test_pqueue():37μs;void test_set():384μs
1。在本例中,不需要有行的副本。可能我过于简化了它。事实上,每行还有另一个信息(例如权重值),这就是为什么我希望在compare类中保留行。