Exemple #1
0
def sort(A, k):
    """
    Sort k-messed array.

    There's an obvious regular sort with `O(n log(n))` complexity or even `O(nk)` solution
     to this problem, however we can do better. We use heap to extract the minimum as we
     shift the `k`-sized window from the beginning to the end.

    Algorithm assumes that `k > 1`.

    Complexity: O(n log(k))
    :param list A: Input array (list)
    :param int k: Max "messiness" distance
    :return None: List `A` is updated
    """
    from basic_data_structures.heaps.min_heap import min_heap_insert, heap_extract_min

    n = len(A)
    H = []
    i = 0
    for i in range(0, k):  # O(k log(k))
        min_heap_insert(H, A[i])
    for i in range(0, n - k):
        A[i] = heap_extract_min(H)  # O(log k)
        min_heap_insert(H, A[i + k])  # O(log k)
    i += 1
    while i < n and len(H) > 0:  # Remaining elements
        A[i] = heap_extract_min(H)
        i += 1
Exemple #2
0
def dijkstra(G, s):
    """
    Dijkstra single-source shortest-paths algorithm.

    In contrast to Bellman-Ford, Dijkstra's algorithm uses greedy strategy on solving
     the single-source shortest paths problems for the case in which all edge weights in
     a DAG are non-negative. It is very similar to BFS, only it prioritises "lightest"
     edges with the smallest estimate (hence the strategy name).

    Greedy approach does not always yield optimal results, but Dijkstra algorithm does
     indeed compute shortest paths. Each time vertex `u` is added to the set `S`, `u.d`
     is already `∂(s, u)` (completely relaxed).

    Dijkstra algorithm is easy to modify to make it solve single-source single-target
     problem. All we need is to stop the while loop once the target vertex is found.

    This implementation uses min-priority queue built with the list vertices keyed by
     their `d` values. Priority queue is built after initialization, but it also needs
     to be rebuilt after series of edge relaxations.

    Complexity: O(E log V) (or O(EV) with this implementation of min-heap). There are at
     most |reachable E| relax operations. If we manage to maintain heap properties after
     each relaxation it is possible to keep extract min operation at `log V` time.
     O(V lg V + E) running time is achievable with a Fibonacci heap.
    :param Graph G: Adjacency list representation of a weighted directed graph with
     non-negative weights.
    :param Vertex s: Starting vertex
    :return None: Graph vertices are updated
    """
    from basic_data_structures.heaps.min_heap import build_min_heap, heap_extract_min

    initialize_single_source(G, s)
    S = []  # Set of vertices whose final shortest-path weights have been determined
    Q = G.V
    while len(Q) > 0:
        build_min_heap(Q)  # Weights might have been updated after relaxation
        u = heap_extract_min(Q, False)  # Heap rebuilding is skipped
        S.append(u)
        for v in G.Adj(u):
            relax(u, v)
    G.V = S  # Optional step to maintain Graph object