Search code examples
dijkstraspace-complexity

Space Complexity of the Priority Queue in this Dijkstra Algorithm


Can anyone tell me the space complexity of the priority queue in this Dijkstra algo. Note that here one vertex can be added to queue more than one time. However, due to the visited set it is not processed more than one time. This is why I am wondering the max size of the queue can get.

def shortestReach(n, edges, start,target):

    adjList = collections.defaultdict(list)

    for parent, child, cost in edges:
        parent -= 1
        child -= 1
        adjList[parent].append((child, cost))
        adjList[child].append((parent, cost))

    priorityQueue = queue.PriorityQueue()
    priorityQueue.put((0, start))
    visited = set()
    while priorityQueue.qsize() > 0:
        costPar, parent = priorityQueue.get()

        if parent == target:
            return costPar

        if parent not in visited:
            for adj in adjList[parent]:
                child, cost = adj
                priorityQueue.put((cost + costPar, child))

        visited.add(parent)

Solution

  • The queue.PriorityQueue class is implemented as a heap data structure:

    With a priority queue, the entries are kept sorted (using the heapq module) and the lowest valued entry is retrieved first.

    So the space complexity is O(n) where n is the number of elements in the priority queue. Your implementation can potentially store a vertex more than once in the priority queue, but each vertex can only be added as many times as there are edges to it, so the space complexity is O(E) where E is the number of edges in the graph.

    In principle it is possible to improve the space complexity to O(V) where V is the number of vertices; to do that, you can implement an augmented priority queue which uses a dictionary to maintain each vertex's current index in the heap, allowing removal by value (as opposed to just polling the minimum element).


    As a side-note, queue.PriorityQueue is a synchronized implementation intended for concurrent access. Dijkstra's algorithm does not require a concurrent priority queue, so your algorithm will be more efficient (in running time) without the overhead of synchronization; you can use the heapq module directly to implement a priority queue in a list, using the heappush and heappop functions to enqueue and poll-min respectively.