4.3 Mindste spændetræ

Mindste spændetræ.

Et spændegraf af en graf er en delgraf, som indeholder alle grafens knuder. Et spændetræ af en sammenhængende graf er en acyklisk spændegraf. En kantvægtet graf er en graf, hvor der er knyttet en vægt eller omkostning til hver kant. Et mindste spændetræ (MST) (eller letteste spændetræ) af en kantvægtet graf er et spændetræ, hvis totale vægt (dvs. summen af kantvægtene) ikke er større end vægten af noget andet spændetræ.

Minimum spænder tree

Antagelser.

Vi vedtager følgende konventioner:

Grundlæggende principper.

Vi minder om to de afgørende egenskaber ved et træ:

Adding en kant til en spænder tree


Et snit i en graf er en opdeling af knudemængden i to disjunkte mængder. En snitkant i et snit er en kant, hvis endepunkter ligger på hver sin side af snittet.

Påstand. (Snitegenskaben)

Betragt et snit i en kantvægtet graf, hvis kantvægte er forskellige. Den snitkant, som har mindst vægt, tilhører grafens mindste spændetræ.

Cut property


Snitegenskaben er gundlaget for vores MST-algoritmer. De er eksempler på en generel problemløsningsteknik, som hedder grådige algoritmer .

Påstand. (Grådig algoritme for MST)

Følgende fremgangsmåde farver alle kanter i et MST i en sammenhængende kantvægtet graf med \(V\) knuder med sort:

Greedy algoritme for
minimum udspændende træ problemet


Datatype for kantvægtede grafer.

Vi repræsenterer vægtede kanter med følgende APG:

public class Edge implements Comparable<Edge>
Edge(int v, int w, double weight)skab en kant mellem v og w med vægt weight
doubleweight()denne kants vægt
inteither()en af kantens endeknuder
voidother(int v)den anden endeknude
intcompareTo(Edge that)sammenlign denne kant med kanten that
StringtoString()tekstuel repræsentation af kanten
Metoderne either() og other() bruges for at få adgang til kantens to endepunkter, sammenligningsmetoden compareTo () sammenligner kanter efter vægt. Kodestumpen Edge.java er en enkel implementering.

Vi repræsenterer kantvægtede grafer med af følgende APG:

public class EdgeWeightedGraph
Graph(int V)skab en graf med V knuder og ingen kanter
Graph(In in)læs en graf fra indputstrømmen in
intV()antal knuder
intE()antal kanter
voidaddEdge(Edge e)tilføj kanten e til denne graf
Iterable<Edge>adj(int v)nabokanter til v
Iterable<Edge>edges()alle kanter i denne graf
StringtoString()tekstuel repræsentation af grafen
Her tillader vi parallelle kanter og løkker. Programmet EdgeWeightedGraph.java implementerer APG’en ved hjælp af kantlisterepræsentationen.

edge-weighted graf representation


APG for MST.

Vi bruger følgende APG til beregning af et MST af en kantvægtet graf:

public class MST
MST(EdgeWeightedGraph G)konstruktør
Iterable<Edge>edges()alle kanter i MST
doubleweight()MST’s samlede vægt
Som testdata bruger vi følgende:

Prims algoritme.

Prims algoritme udvider et træ med en kant ad gangen. Begynd med en enkel knude som træets eneste knude. Tilføj derefter \(V-1\) kanter til træet, ved gentagne gange at tage den letteste kant blandt de kanter, der forbinder en knude i træet med en knude uden for træet. (Med andre ord defineres snittet af de knuder, der tilhører træet.)

Prim's MST algorithm


Beskrivelsen af Prim algoritme foroven i en enkelt sætning lader det centrale spørgsmål ubesvaret: Hvordan kan vi (effektivt) finde den letteste snitkant?

Påstand.

Prims algoritme beregner MST af en sammenhængende, kantvægtet graf. Den sløve version af Prims algoritme bruger plads proportional med \(E\) og værstefaldstid proportional med \(E \log E\) for at beregne MST af en sammenhængende kantvægtet graf med \(E\) kanter og \(V\) knuder. Den ivrige versionen af Prims algoritme bruger plads proportional med \(V\) og værstefaldstid proportional med \(E\log V\).


Kruskals algoritme.

Kruskals algoritme behandler samtlige kanter i rækkefølge efter deres vægt, fra lettest til tungest. Hver kant farves sort, hvis den ikke danner en kreds med de andre sorte kanter. Denne proces standser efter at \(V–1\) kanter er farvet sort, som nu danner et minste spændetræ. De sorte kanter danner altså undervejs en skov af træer, der gradvist vokser sammen til et en enkelt træ.

Kruskal's algoritme til mindste udspændende træ problem


For at implementere Kruskals algoritme bruger vi en prioritetskø til at behandle kanterne i rækkefølge efter vægt, en forén og find-datastrukturen til at identificere kredse og en kø til at indsamle MST-kanter. Programmet KruskalMST.java implementerer Kruskals algoritme på den måde. DPrioritetskøen er fra MinPQ.java , sammenhængskomponenterne fra UF.java , og køen fra Queue.java .

Påstand.

Kruskals algoritme beregner det minste spændetræ af en sammenhængende kantvægtet graf med \(E\) kanter og \(V\) knuder i ekstra plads proportional med \(E\) og værstefaldstid proportional med \(E\log E\).