0

We want to find an item in a linked list, do something with the item, and then delete it.

from collections import deque

q = deque([(12, 'apples'), (32, 'oranges'), (42, 'pears'), (12, 'peaches')])
john_smith_id = 42

for customer in q:
    id, data = customer
    if id == john_smith_id:
        myfunction(data)  # do something with John Smith's data
        q.remove(customer)
        break

My question is about the line q.remove(customer). This should ideally be O(1) since we've already found the customer in the linked list, but I fear it may be traversing the entire linked list.

What's the correct way to do this?

martineau
  • 119,623
  • 25
  • 170
  • 301
tmkadamcz
  • 119
  • 6
  • 1
    What is exactly what you want? A data structure that supports finding and deletion in O(1)? By the way are you going to have repeated ids? – Dani Mesejo Oct 25 '20 at 22:27
  • 4
    Seems like an XY problem--even if you do this, the overall operation is still O(n) either way so you still (likely?) have the wrong data structure for your use case. Why not use a dict? [Sort of related](https://stackoverflow.com/questions/32530065). – ggorlen Oct 25 '20 at 22:28
  • Thanks. Thinking about this more, I think the entire linked list approach was wrong, and I should use a dictionary. I got confused because I originally used a list, then thought about improving deletion, which led me to think about a linked list. But of course a dictionary is actually better, since access is O(1) too. Sorry! :/ – tmkadamcz Oct 25 '20 at 22:32
  • yeah, ggorlen beat me to it. – tmkadamcz Oct 25 '20 at 22:33
  • A `deque` has a different use case than a dict. If you want other deque features, stick with it. – tdelaney Oct 25 '20 at 22:33
  • What's the etiquette here, should I delete my question? – tmkadamcz Oct 25 '20 at 22:33
  • 1
    BTW size of the data and use case matters a lot--if your list is a couple hundred elements and it's not in the critical path of the app, then it really doesn't matter what time complexity it is. You could also code your own doubly linked list that does support O(1) deletion with ordering, or a linked hash map, but seems almost certainly the wrong way to go. Use `collections.deque` as a pure queue, and a rotatable structure. Dicts are pretty much the solution for non-list structures 98% of the time though, they're ordered, O(1) lookup/deletion/insertion etc. – ggorlen Oct 25 '20 at 22:34

1 Answers1

0

It's re-traversing the list.

If you want a linked list with that kind of functionality, don't use collections.deque. collections.deque is a deque type, not a linked list type. It uses an unrolled linked list under the hood, but it doesn't support all possible linked list functionality. With the way the unrolling is implemented, it can't even support the operation you want - the implementation uses 64-element chunks, and it doesn't support partially-empty middle chunks, so there's no way to delete an element from the middle without the operation rippling all the way to one of the ends of the list.

A linked list doesn't seem like a great choice for your data structure anyway. It looks more like a job for a dict.

user2357112
  • 260,549
  • 28
  • 431
  • 505