简体   繁体   中英

priority queue size is 0 but priority_queue top returns an element

I came across this weird behaviour of priority_queue in c++ while solving a leetcode puzzle. The priority_queue has a size of zero but on doing pq.top() it returns an element which is quite weird to me.

class Solution {
public:
    int lastStoneWeight(vector<int>& stones) {
        
        priority_queue <int> pq ;
        
        for(auto &it: stones){
            pq.push(it);
        }
           
        while(pq.size() >1){
            int x = pq.top(); pq.pop();
            int y = pq.top(); pq.pop();
         
            if(x>y){
                pq.push(x-y);
            }
            if(y> x){
                pq.push(y-x);
            }
        }
        
        cout <<"pq.size() is "<< pq.size() << endl;
        cout <<"pq.top() is "<< pq.top() << endl;
        if(pq.size() == 0){
            return 0;
        }
        return pq.top();
        
    }
};

When this code is run for input [2,2] this is what I get on doing cout. Note that i had two elements in priority_queue and i have popped out both elements.

pq.size() is 0
pq.top() is 2

As others have pointed out your code, specifically the second cout line, exhibits undefined behaviour. Why is that?

Have a look at what std::priority_queue 's top does :

Reference to the top element as if obtained by a call to c.front()

( c here refers to the instance of the underlying container, which is std::vector by default).

std::vector::front() has this to say:

Returns a reference to the first element in the container.

Calling front on an empty container is undefined.

The rationale here is that top returns by const_reference and an empty container has no valid values it could refer to.

If you remove the second cout , your code will be fine.


A note on what value you get: This depends on the implementation of your compiler and the library that goes with it. As stated this is highly undefined behaviour. However, the typical implementation of a std::vector (remember, the underlying container) is to never release the allocated memory it uses. Even if you empty it.

So, since you are dealing with int s here, the last value that was at position 0 of the vector (ie front() ) will be retuned despite having been destroyed. The destuction of an int is a noop, and the value remains unchanged in memory. It's still not a legal C++ program.

Doing pop operation on an empty priority queue is an undefined behaviour and it can give anything as output.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM