0

I know that pop the last element of the list takes O(1). And after reading this post

What is the time complexity of popping elements from list in Python?

I notice that if we pop an arbitrary number from a list takes O(n) since all the pointers need to shift one position up.

But for the set, there is no order and no index. So I am not sure if there is still pointers in set?

If not, would the pop() for set is O(1)?

Thanks.

domino
  • 89
  • 7
  • Unduping. That dupe target doesn't address `pop` (which has surprisingly weird time complexity characteristics). – user2357112 Mar 12 '21 at 00:46
  • What happened when you ran your timing tests on popping form a set? What do you find confusing about your results? – Prune Mar 12 '21 at 01:00

1 Answers1

2

On modern CPython implementations, pop takes amortized constant-ish time (I'll explain further). On Python 2, it's usually the same, but performance can degrade heavily in certain cases.

A Python set is based on a hash table, and pop has to find an occupied entry in the table to remove and return. If it searched from the start of the table every time, this would take time proportional to the number of empty leading entries, and it would get slower with every pop.

To avoid this, the standard CPython implementation tries to remember the position of the last popped entry, to speed up sequences of pops. CPython 3.5+ has a dedicated finger member in the set memory layout to store this position, but earlier versions abuse the hash field of the first hash table entry to store this index.

On any Python version, removing all elements from a set with a sequence of pop operations will take time proportional to the size of the underlying hash table, which is usually within a small constant factor of the original number of elements (unless you'd already removed a bunch of elements). Mixing insertions and pop can interfere heavily with this on Python 2 if inserted elements land in hash table index 0, trashing the search finger. This is much less of an issue on Python 3.

user2357112
  • 260,549
  • 28
  • 431
  • 505