tdt4120

En samling av viktige algoritmer til eksamen

Tellesortering

function counting-sort(A, B, k)
    let C[0...k] be a new array
    for i = 0 to k
       C[i] = 0
    for j = 1 to A.length
       C[A[j]] += 1
    for i = 1 to k
       C[i] = C[i] + C[i - 1]
    for j = A.length downto 1
       B[C[A[j]]] = A[j]
       C[A[j]] -= 1

Radikssortering

function radix-sort(A, d)
    for i = 1 to d
       sort* A by digit d

Bøttesortering

function bucket-sort(A)
    n = A.length
    create B[0...n-1]
    for i = 0 to n
       make B[i] an empty list
    for i = 1 to n
       add A[i] to B[floor(nA[i])]
    for i = 0 to n - 1
       sort list B[i] #Bruker insertion sort
    concatenate B[0]...B[n - 1]

Huffman

Input: Alfabet $C = \{c,…\}$ med frekvenser $c.freq$

Output: Binær koding som minimerer forventet kodelengde $\sum_{c\;∈\;C}c.freq × length(code(c))$.

Prøver en grådig algoritme

 function huffman(C)
  #C Frekvenser
  # Q pri-kø
  n = length(C) # |C|
  Q = C
  for i = 1:n - 1
   # allocate a new node z
   x = extract_min(Q)
   y = extract_min(Q)
   z.left, z.right = x, y
   z.freq = x.freq + y.freq
   insert(Q, z)
 end
 return extract_min(Q)

Traversering generelt: Vi besøker noder, oppdager noder langs kanter og vedlikeholder en huskeliste.

Besøker nodene og noterer naboene til nodene, helt til lista er tom; da har vi besøkt alle vi kan.

Passer på om vi får overlappende naboer mellom forskjellige noder.

Så lenge vi bruker en FIFO-kø (dvs., BFS) så finner vi korteste vei; ellers risikerer vi å finne noder via omveier!

function bfs(G, s)
  for vertex in G.V - {s}
    vertex.color = WHITE
    vertex.d = Inf
    vertex.π = nothing
  s.color = GREY
  s.d = 0
  s.π = nothing
  Q = empty
  enqueue(Q, s)
  while Q != empty
    u = dequeue(Q) #FIFO
    for vertex in G.adj[u]
      if vertex.color == WHITE
        #Add vertex to queue
        vertex.color = GREY
        vertex.d = u.d + 1
        enqueue(Q, vertex)
    u.color = BLACK

DFS, flood-fill: Fyll rekursivt nord, øst, sør, vest

time;
function dfs(G)
  for vertex in G.v
    u.color = WHITE
    u.pi = nothing
  time = 0 #global variabel, en counter
  for vertex in G.v
    if vertex.color == WHITE
      dfs_visit(G, vertex)

function dfs_visit(G, vertex)
  time = time + 1
  vertex.d = time #Discover time
  vertex.color = GREY
  for v in G.adj[vertex]
    if v.color == WHITE
      v.pi = vertex
      dfs_visit(G, v)
  vertex.color = BLACK
  time = time + 1
  vertex.f = time #Finish time

Generisk

Input: En urettet graf $G = (V, E)$ og en vekt-funksjon $w: E \rightarrow R$

Output: En asyklisk delmengde $T ⊆ E$ som kobler sammen nodene i $V$ og minimerer vektsummen $w(T) = \sum_{(u,v) ∈ T} w(u,v)$.

function generic_mst(G, w)
  A = []
  while A does not form a spanning tree,
   find an edge (u, v) that is safe for A
    push!(A, (u, v))
  end
  return A
end

Kruskal

To skoger på en gang

function mst_kruskal(G, w)
  A = []
  for each vertex v in G.V
    make_set(v)
  end
  sort G.E by w # Sorter etter vekting
  for each edge (u,v) in G.E
    if find_set(u) != find_set(v)
      # en trygg kant
      push!(A, (u, v))
      union(u, v) #Egen definert union funksjon, se lenger oppe
    end
  end
  return A
Operasjon Antall Kjøretid
MAKE-SET $V$ $O(1)$
Sortering $1$ $O(E log(E))$
FIND-SET $O(E)$ $O(log(V))$
UNION $O(E)$ $O(log(V))$

Prims

function mst_prim(G, w, r)
  for each u in G.V
    u.key = Inf
    u.pi = nothing
  end
  r.key = 0
  Q = G.V
  while Q != empty
    u = extract_min(Q)
    for each v in G.adj(u)
      if v in Q and w(u,v) < v.key
        v.pi = u
        v.key = w(u, v)
      end
    end
  end
Operasjon Antall Kjøretid
BUILD-MIN-HEAP $1$ $O(V)$
EXTRACT-MIN $V$ $O(log(V))$
DECREASE-KEY $E$ $O(log(V))$

Kan forbedres med en Fib.haug (Fib heap). Blir da $O(E + V log(V))$.

DAG-Shortest-Path

topologically sort G
initialize_single_source(G, s)
for each vertex v in V
  for each edge (u, v) in E
    relax(u, v, w)
  end
end

function initialize_single_source(G, s)
  for each vertex v in V
    v.d = Inf
    v.\pi = nothing
  end
  s.d = 0
end

function relax(u, v, w)
  if v.d > u.d + w(u, v)
    v.d = u.d + w(u, v)
    v.\pi = u
  end
end
Operasjon Antall Kjøretid
Topologisk-sortering 1 $\Theta(V + E)$
Initialisering 1 $\Theta(V)$
RELAX E $\Theta(1)$

Bellman-ford

function bellman_ford(G, w, s)
  initialize_single_source(G, s)
  for i = 1 to |G.V| - 1
    for each edge (u, v) in G.E
      relax(u, v w)
    end
  end
  for each edge (u, v) in G.E
    if v.d > u.d + w(u, v)
      return false
    end
  end
  return true
Operasjon Antall Kjøretid
Initialisering 1 $\Theta(V)$
RELAX $V - 1$ $\Theta(E)$
RELAX $O(V)$ $\Theta(E)$

$Totalt: O(VE)$

Dijkstras

function dijkstra(G, w, s)
  initialize_single_source(G, s)
  S = []
  Q. = G.V #Queue
  while Q != empty
    u = extract_min(Q) # Korteste stien til start
    push!(S, u)
    for each vertex v in G.adj[u]
      relax(u, v, w)
    end
  end
end
Operasjon Antall Kjøretid
Initialisering 1 $\Theta(V)$
BUILD-HEAP 1 $\Theta(V)$
EXTRACT-MIN $V$ $O(lg V)$
DECREASE-KEY $E$ $O(lg V)$

Total: O(V lg V + E lg V)

Med binærheap: bedre enn lineært søk for $E = o(V^2/lg V)$

Med Fibonacci-heap: DECREASE-KEY er $O(1)$: vi får $O(V lg V + E)$