Priority_queue大小的意外行为

时间:2018-08-03 19:23:11

标签: c++

我正在编写该问题的代码。遇到问题时整数流的中位数。请注意,此问题不是算法上的问题,而是priority_queue大小的模棱两可的行为。

#include <bits/stdc++.h>
using namespace std;
priority_queue<double> small;
priority_queue<double, vector<double>, greater<double> > large;
void rebalance()
{
    cout << "Initial size\n";
    cout << "small " << small.size() << " large " << large.size() << endl;
    if (small.size() - large.size()>1)
    {
        large.push(small.top());
        small.pop();
    }
    else if (large.size() - small.size()>1)
    {
        cout << "Unexpectedly goes here\n";
        cout << "garbage size difference " << large.size() - small.size() << endl;
        small.push(large.top());
        large.pop();
    }
}
void addNum(int num) {
    if (small.size() == 0 || num<small.top())
    {
        small.push(num);
    }
    else
    {
        large.push(num);
    }
    rebalance();
}

double findMedian() {
    if (small.size() == large.size())
    {
        double ans = (small.top() + large.top()) / 2.0;
        return ans;
    }
    else if (small.size()>large.size())
    {
        return (double)small.top();
    }
    else
    {
        return (double)large.top();
    }
}
int main()
{
    std::ios_base::sync_with_stdio(false);
    int num = 5;
    addNum(num);
    cout << findMedian() << endl;
    return 0;
}

此代码的输出为

   Initial size
   small 1 large 0
   Unexpectedly goes here
   garbage size difference 18446744073709551615
   fish: “./a.out” terminated by signal SIGSEGV (Address boundary error)

rebalance函数中,small的初始大小为1,较大的值为0,这表明循环既不应输入if条件也不应输入else if条件但是循环会进入 else if 条件,并且大小为垃圾值。为什么会这样?此外,我尝试将较小和较大的大小保存在整数变量中,然后将它们与条件语句进行比较,从而导致接受代码。因此,该算法可以处理正确性。

什么导致了这个垃圾值?

1 个答案:

答案 0 :(得分:2)

else if(large.size()-small.size()>1)

size()返回一个无符号数字。无符号数永远不能为负数,因此,如果为负数,它将环绕为可能的最大数,然后从那里倒退。由于large的大小为0,而small的大小为1,因此0 - 1给您18446744073709551615。我相信您要尝试做的事情应该表达为

if(small.size() < large.size())
{
    small.push(large.top());
    large.pop():
} 
else if(large.size() < small.size())
{
    large.push(small.top());
    small.pop();
}