logo

Hierholzers algoritme for rettet graf

Gitt en rettet Eulersk graf er oppgaven å skrive ut en Euler krets . En Euler-krets er en bane som krysser hver kant av en graf nøyaktig én gang, og banen ender på startpunktet.

Note: Den gitte grafen inneholder en Euler-krets.

Eksempel:



Inngang : Rettet graf

Hierholzers algoritme for rettet graf' title=

Produksjon: 0 3 4 0 2 1 0

Forutsetninger:

  • Vi har diskutert problem med å finne ut om en gitt graf er Eulerian eller ikke for en urettet graf
  • Betingelser for Eulerisk krets i en rettet Grpag: (1) Alle toppunkter tilhører en enkelt sterkt tilkoblet komponent. (2) Alle toppunkter har samme inn-grad og ut-grad. Merk at for en urettet graf er betingelsen forskjellig (alle toppunkter har jevn grad)

Nærme:

  1. Velg et hvilket som helst startpunkt v og følg et spor av kanter fra det toppunktet til du går tilbake til v. Det er ikke mulig å bli sittende fast ved noe annet toppunkt enn v fordi indegree og outdegree for hvert toppunkt må være det samme når stien går inn i et annet toppunkt w det må være en ubrukt kant som forlater w. Turen dannet på denne måten er en lukket tur, men dekker kanskje ikke alle toppunktene og kantene på den første grafen.
  2. Så lenge det eksisterer et toppunkt u som tilhører den nåværende turen, men som har tilstøtende kanter som ikke er en del av turen, starter du en annen sti fra u følger ubrukte kanter til du går tilbake til u og blir med på turen dannet på denne måten til forrige tur.

Illustrasjon:

Ta eksempel på grafen ovenfor med 5 noder: adj = {{2 3} {0} {1} {4} {0}}.

  1. Start ved toppunktet 0 :
    • Gjeldende bane: [0]
    • Krets: []
  2. Toppunkt 0 → 3 :
    • Nåværende bane: [0 3]
    • Krets: []
  3. Toppunkt 3 → 4 :
    • Nåværende bane: [0 3 4]
    • Krets: []
  4. Toppunkt 4 → 0 :
    • Nåværende bane: [0 3 4 0]
    • Krets: []
  5. Toppunkt 0 → 2 :
    • Nåværende bane: [0 3 4 0 2]
    • Krets: []
  6. Toppunkt 2 → 1 :
    • Gjeldende bane: [0 3 4 0 2 1]
    • Krets: []
  7. Toppunkt 1 → 0 :
    • Gjeldende bane: [0 3 4 0 2 1 0]
    • Krets: []
  8. Gå tilbake til toppunkt 0 : Legg til 0 til kretsen.
    • Gjeldende bane: [0 3 4 0 2 1]
    • Krets: [0]
  9. Gå tilbake til toppunkt 1 : Legg til 1 til kretsen.
    • Nåværende bane: [0 3 4 0 2]
    • Krets: [0 1]
  10. Gå tilbake til toppunkt 2 : Legg til 2 til kretsen.
    • Nåværende bane: [0 3 4 0]
    • Krets: [0 1 2]
  11. Gå tilbake til toppunkt 0 : Legg til 0 til kretsen.
    • Nåværende bane: [0 3 4]
    • Krets: [0 1 2 0]
  12. Gå tilbake til toppunkt 4 : Legg til 4 til kretsen.
    • Nåværende bane: [0 3]
    • Krets: [0 1 2 0 4]
  13. Gå tilbake til toppunkt 3 : Legg til 3 til kretsen.
    • Gjeldende bane: [0]
    • Krets: [0 1 2 0 4 3]
  14. Gå tilbake til toppunkt 0 : Legg til 0 til kretsen.
    • Gjeldende bane: []
    • Krets: [0 1 2 0 4 3 0]

Nedenfor er implementeringen for tilnærmingen ovenfor: 

C++
// C++ program to print Eulerian circuit in given // directed graph using Hierholzer algorithm #include    using namespace std; // Function to print Eulerian circuit vector<int> printCircuit(vector<vector<int>> &adj) {  int n = adj.size();  if (n == 0)  return {};  // Maintain a stack to keep vertices  // We can start from any vertex here we start with 0  vector<int> currPath;  currPath.push_back(0);  // list to store final circuit  vector<int> circuit;  while (currPath.size() > 0) {  int currNode = currPath[currPath.size() - 1];  // If there's remaining edge in adjacency list  // of the current vertex  if (adj[currNode].size() > 0) {    // Find and remove the next vertex that is  // adjacent to the current vertex  int nextNode = adj[currNode].back();  adj[currNode].pop_back();  // Push the new vertex to the stack  currPath.push_back(nextNode);  }  // back-track to find remaining circuit  else {  // Remove the current vertex and  // put it in the circuit  circuit.push_back(currPath.back());  currPath.pop_back();  }  }  // reverse the result vector   reverse(circuit.begin() circuit.end());    return circuit; } int main() {  vector<vector<int>> adj = {{2 3} {0} {1} {4} {0}};  vector<int> ans = printCircuit(adj);    for (auto v: ans) cout << v << ' ';  cout << endl;  return 0; } 
Java
// Java program to print Eulerian circuit in given // directed graph using Hierholzer algorithm import java.util.*; class GfG {  // Function to print Eulerian circuit  static List<Integer> printCircuit(List<List<Integer>> adj) {  int n = adj.size();  if (n == 0)  return new ArrayList<>();  // Maintain a stack to keep vertices  // We can start from any vertex here we start with 0  List<Integer> currPath = new ArrayList<>();  currPath.add(0);  // list to store final circuit  List<Integer> circuit = new ArrayList<>();  while (currPath.size() > 0) {  int currNode = currPath.get(currPath.size() - 1);  // If there's remaining edge in adjacency list  // of the current vertex  if (adj.get(currNode).size() > 0) {  // Find and remove the next vertex that is  // adjacent to the current vertex  int nextNode = adj.get(currNode).get(adj.get(currNode).size() - 1);  adj.get(currNode).remove(adj.get(currNode).size() - 1);  // Push the new vertex to the stack  currPath.add(nextNode);  }  // back-track to find remaining circuit  else {  // Remove the current vertex and  // put it in the circuit  circuit.add(currPath.get(currPath.size() - 1));  currPath.remove(currPath.size() - 1);  }  }  // reverse the result vector  Collections.reverse(circuit);  return circuit;  }  public static void main(String[] args) {  List<List<Integer>> adj = new ArrayList<>();  adj.add(new ArrayList<>(Arrays.asList(2 3)));  adj.add(new ArrayList<>(Arrays.asList(0)));   adj.add(new ArrayList<>(Arrays.asList(1)));   adj.add(new ArrayList<>(Arrays.asList(4)));   adj.add(new ArrayList<>(Arrays.asList(0)));   List<Integer> ans = printCircuit(adj);  for (int v : ans) System.out.print(v + ' ');  System.out.println();  } } 
Python
# Python program to print Eulerian circuit in given # directed graph using Hierholzer algorithm # Function to print Eulerian circuit def printCircuit(adj): n = len(adj) if n == 0: return [] # Maintain a stack to keep vertices # We can start from any vertex here we start with 0 currPath = [0] # list to store final circuit circuit = [] while len(currPath) > 0: currNode = currPath[-1] # If there's remaining edge in adjacency list # of the current vertex if len(adj[currNode]) > 0: # Find and remove the next vertex that is # adjacent to the current vertex nextNode = adj[currNode].pop() # Push the new vertex to the stack currPath.append(nextNode) # back-track to find remaining circuit else: # Remove the current vertex and # put it in the circuit circuit.append(currPath.pop()) # reverse the result vector circuit.reverse() return circuit if __name__ == '__main__': adj = [[2 3] [0] [1] [4] [0]] ans = printCircuit(adj) for v in ans: print(v end=' ') print() 
C#
// C# program to print Eulerian circuit in given // directed graph using Hierholzer algorithm using System; using System.Collections.Generic; class GfG {    // Function to print Eulerian circuit  static List<int> printCircuit(List<List<int>> adj) {  int n = adj.Count;  if (n == 0)  return new List<int>();  // Maintain a stack to keep vertices  // We can start from any vertex here we start with 0  List<int> currPath = new List<int> { 0 };  // list to store final circuit  List<int> circuit = new List<int>();  while (currPath.Count > 0) {  int currNode = currPath[currPath.Count - 1];  // If there's remaining edge in adjacency list  // of the current vertex  if (adj[currNode].Count > 0) {  // Find and remove the next vertex that is  // adjacent to the current vertex  int nextNode = adj[currNode][adj[currNode].Count - 1];  adj[currNode].RemoveAt(adj[currNode].Count - 1);  // Push the new vertex to the stack  currPath.Add(nextNode);  }  // back-track to find remaining circuit  else {  // Remove the current vertex and  // put it in the circuit  circuit.Add(currPath[currPath.Count - 1]);  currPath.RemoveAt(currPath.Count - 1);  }  }  // reverse the result vector  circuit.Reverse();  return circuit;  }  static void Main(string[] args) {  List<List<int>> adj = new List<List<int>> {  new List<int> { 2 3 }  new List<int> { 0 }  new List<int> { 1 }  new List<int> { 4 }  new List<int> { 0 }  };  List<int> ans = printCircuit(adj);  foreach (int v in ans) {  Console.Write(v + ' ');  }  Console.WriteLine();  } } 
JavaScript
// JavaScript program to print Eulerian circuit in given // directed graph using Hierholzer algorithm // Function to print Eulerian circuit function printCircuit(adj) {  let n = adj.length;  if (n === 0)  return [];  // Maintain a stack to keep vertices  // We can start from any vertex here we start with 0  let currPath = [0];  // list to store final circuit  let circuit = [];  while (currPath.length > 0) {  let currNode = currPath[currPath.length - 1];  // If there's remaining edge in adjacency list  // of the current vertex  if (adj[currNode].length > 0) {  // Find and remove the next vertex that is  // adjacent to the current vertex  let nextNode = adj[currNode].pop();  // Push the new vertex to the stack  currPath.push(nextNode);  }  // back-track to find remaining circuit  else {  // Remove the current vertex and  // put it in the circuit  circuit.push(currPath.pop());  }  }  // reverse the result vector  circuit.reverse();  return circuit; } let adj = [[2 3] [0] [1] [4] [0]]; let ans = printCircuit(adj); for (let v of ans) {  console.log(v ' '); } 

Produksjon
0 3 4 0 2 1 0 

Tidskompleksitet:  O(V + E) hvor V er antall toppunkter og E er antall kanter i grafen. Grunnen til dette er fordi algoritmen utfører et dybde-først-søk (DFS) og besøker hvert toppunkt og hver kant nøyaktig én gang. Så for hvert toppunkt tar det O(1) tid å besøke det, og for hver kant tar det O(1) tid å krysse det.

Romkompleksitet: O(V + E) som algoritmen bruker en stabel for å lagre gjeldende bane og en liste for å lagre den endelige kretsen. Maksimal størrelse på stabelen kan i verste fall være V + E, så plasskompleksiteten er O(V + E).

Lag quiz