Блог пользователя Halym2007

Автор Halym2007, история, 10 месяцев назад, По-английски

both code did same.what is the difference?

First one : 
set <int> s;
s.insert (1);s.insert (3);s.insert (5);
auto tr = s.lower_bound (2);
s.erase (tr);<-----------here
--------------------------
Second one : 
set <int> s;
s.insert (1);s.insert (3);s.insert (5);
auto tr = s.lower_bound (2);
s.erase (*tr);<-----------here
  • Проголосовать: нравится
  • +40
  • Проголосовать: не нравится

»
10 месяцев назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится

Auto comment: topic has been updated by Halym2007 (previous revision, new revision, compare).

»
10 месяцев назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится

Auto comment: topic has been updated by Halym2007 (previous revision, new revision, compare).

»
10 месяцев назад, # |
Rev. 4   Проголосовать: нравится -22 Проголосовать: не нравится

.

»
10 месяцев назад, # |
Rev. 3   Проголосовать: нравится +68 Проголосовать: не нравится

The real difference is when you use multiset and have multiple values, the first code removes only one occurrence of 3(lower_bound of 2 in the set is 3) but the second one removes all of them.

The reason is that tr is a pointer to one element, while *tr is the value of the pointer, which when used in a multiset, removes all occurrences of that element.

  • »
    »
    10 месяцев назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Agree, but what is the difference between these two for a set.

    • »
      »
      »
      10 месяцев назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      There is no difference in the final result for an ordered_set (like in this case).

    • »
      »
      »
      10 месяцев назад, # ^ |
        Проголосовать: нравится +18 Проголосовать: не нравится

      Difference will be in speed of execution. If you pass value to erase function, std::set has to search for it. If you pass pointer, it doesn't.

»
10 месяцев назад, # |
  Проголосовать: нравится +1 Проголосовать: не нравится

tr is an iterator so is pointing to the memory address while *tr means dereferencing the iterator and is accessing value at that memory address

»
10 месяцев назад, # |
  Проголосовать: нравится +16 Проголосовать: не нравится

First One s.erase(tr) -> O(1)

Second One s.erase(*tr) -> O(logN)

  • »
    »
    10 месяцев назад, # ^ |
    Rev. 3   Проголосовать: нравится +37 Проголосовать: не нравится

    Are you sure s.erase(tr) is O(1), shouldn't it also be O(log N) since std::set is implemented with red-black trees and deletion in a red-black tree is O(log N)?

    • »
      »
      »
      10 месяцев назад, # ^ |
        Проголосовать: нравится +29 Проголосовать: не нравится

      Upon using iterator, it's constant time removal. However, I am not sure why such a useful blog is downvoted !

  • »
    »
    10 месяцев назад, # ^ |
      Проголосовать: нравится +24 Проголосовать: не нравится

    Remember that complexity is an amortized constant, not a worst-time constant. [reference]

    • »
      »
      »
      10 месяцев назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Can you please elaborate how that is true? I see that it is written but don't understand how it is O(1) amortized...

      • »
        »
        »
        »
        10 месяцев назад, # ^ |
          Проголосовать: нравится +3 Проголосовать: не нравится

        You can not remove from rb tree single node in O(1). Because multiple rotations can be met. But in practice, this is almost always single rotation. So this is not amortized O(1), but O(1) with high probability.

»
10 месяцев назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

The first code snippet erases the element using the iterator directly.

The second code snippet dereferences the iterator to get the element's value before erasing.