Search code examples
algorithmoptimizationdata-structurestime-complexitycomputer-science

What is the time complexity for deletion in singly and doubly linked lists?


If we don't know the position of the node, is it true that both singly linked list and doubly linked list take O(n) time to delete?

My understanding is that we need to traverse to node to know the previous pointer of the node and next pointer of node in singly linked list. The time complexity for singly linked list to delete is O(n) as a result.

For doubly linked list, since we know the previous and next pointers of the node we want to delete, the time complexity is O(1).


Solution

  • It's O(n) to locate a node in both cases (pseudo-code follows here, and in all cases below):

    def locate(key):
        ptr = head
        while ptr != null:
            if ptr.key == key:
                return ptr
            ptr = ptr.next
        return null
    

    It's O(1) to delete a node in a doubly linked list given only its pointer, because you can get to the previous node easily:

    def del (ptr):
        if ptr == head: # head is special case
            head = ptr.next
            free ptr
            return
    
        ptr.prev.next = ptr.next
        free ptr
    

    For those same conditions (only having the pointer), it's O(n) to delete a node in a singly linked list because you need to first locate the node before the one you want to delete:

    def del (ptr):
        if ptr == head: # head is special case
            head = ptr.next
            free ptr
            return
    
        prev = head
        while prev.next != ptr:
            prev = prev.next
        prev.next = ptr.next
        free ptr
    

    However, two O(n) operations is still O(n) since it's linearly dependent on the number of nodes.

    Hence, to delete a node you don't yet have a pointer to, is O(n) in both cases, it's just the work done for each n would be bigger for the singly linked list, if you did it naively (as "locate node to delete" then "locate node before that one").


    Typically though, you wouldn't do that. Your delete function would remember the previous node when advancing so that, once you'd found the one to delete, you also have the one before it so you wouldn't need another search.

    That could go something like this, with us actually searching for the element before the one you want to delete:

    def del (key):
        if head == null: # no action on empty list
            return
    
        if head.key == key: # head is special case
            temp = head
            head = head.next
            free temp
            return
    
        prev = head
        while prev.next != null:
            if prev.next.key == key:
                temp = prev.next
                prev.next = temp.next
                free temp
                return
            prev = prev.next