Hierholzerův algoritmus pro orientovaný graf

Hierholzerův algoritmus pro orientovaný graf

Daný řízený eulerovský graf je úkolem vytisknout . Eulerův obvod je cesta, která prochází každou hranou grafu přesně jednou a končí na počátečním vrcholu.

Poznámka: Daný graf obsahuje Eulerův obvod.

Příklad:



Vstup: Orientovaný graf

Hierholzerův algoritmus pro orientovaný graf

výstup: 0 3 4 0 2 1 0

Předpoklady:

  • problém zjistit, zda je daný graf eulerovský či nikoliv pro neorientovaný graf
  • Podmínky pro eulerovský obvod v řízeném grpagu: (1) Všechny vrcholy patří do jediné silně propojené komponenty. (2) Všechny vrcholy mají stejný in-degree a out-degree. Všimněte si, že pro neorientovaný graf je podmínka jiná (všechny vrcholy mají sudý stupeň)

Přístup:

  1. Vyberte si libovolný počáteční vrchol v a sledujte stopu hran z tohoto vrcholu, dokud se nevrátíte do v. Není možné uvíznout v žádném jiném vrcholu než v, protože indegre a outdegree každého vrcholu musí být stejné, když stopa vstupuje do jiného vrcholu w musí tam být nepoužitá hrana opouštějící w. Prohlídka vytvořená tímto způsobem je uzavřená, ale nemusí pokrývat všechny vrcholy a hrany počátečního grafu.
  2. Dokud existuje vrchol u, který patří k aktuální prohlídce, ale má přilehlé okraje, které nejsou součástí trasy, začněte další stezku od u po nepoužívaných hranách, dokud se nevrátíte k u a připojte se k takto vytvořené trase k předchozí trase.

Ilustrace:

Vezměme si příklad výše uvedeného grafu s 5 uzly: adj = {{2 3} {0} {1} {4} {0}}.

  1. Začněte ve vrcholu 0 :
    • Aktuální cesta: [0]
    • Obvod: []
  2. Vertex 0 → 3 :
    • Aktuální cesta: [0 3]
    • Obvod: []
  3. Vertex 3 → 4 :
    • Aktuální cesta: [0 3 4]
    • Obvod: []
  4. Vertex 4 → 0 :
    • Aktuální cesta: [0 3 4 0]
    • Obvod: []
  5. Vertex 0 → 2 :
    • Aktuální cesta: [0 3 4 0 2]
    • Obvod: []
  6. Vertex 2 → 1 :
    • Aktuální cesta: [0 3 4 0 2 1]
    • Obvod: []
  7. Vrchol 1 → 0 :
    • Aktuální cesta: [0 3 4 0 2 1 0]
    • Obvod: []
  8. Zpět k vrcholu 0 : Přidejte 0 do obvodu.
    • Aktuální cesta: [0 3 4 0 2 1]
    • Okruh: [0]
  9. Zpět k vrcholu 1 : Přidejte 1 do obvodu.
    • Aktuální cesta: [0 3 4 0 2]
    • Okruh: [0 1]
  10. Zpět k vrcholu 2 : Přidejte 2 do obvodu.
    • Aktuální cesta: [0 3 4 0]
    • Okruh: [0 1 2]
  11. Zpět k vrcholu 0 : Přidejte 0 do obvodu.
    • Aktuální cesta: [0 3 4]
    • Okruh: [0 1 2 0]
  12. Zpět k vrcholu 4 : Přidejte 4 do obvodu.
    • Aktuální cesta: [0 3]
    • Okruh: [0 1 2 0 4]
  13. Zpět k vrcholu 3 : Přidejte 3 do obvodu.
    • Aktuální cesta: [0]
    • Okruh: [0 1 2 0 4 3]
  14. Zpět k vrcholu 0 : Přidejte 0 do obvodu.
    • Aktuální cesta: []
    • Okruh: [0 1 2 0 4 3 0]

Níže je uvedena implementace výše uvedeného přístupu: 

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       ' '  );   }   

Výstup
0 3 4 0 2 1 0  

Časová náročnost:  O(V + E) kde V je počet vrcholů a E je počet hran v grafu. Důvodem je to, že algoritmus provádí prohledávání do hloubky (DFS) a navštěvuje každý vrchol a každou hranu přesně jednou. Takže pro každý vrchol trvá O(1) čas, než jej navštíví, a pro každou hranu trvá O(1) čas, než jej projde.

Složitost prostoru  : O(V + E) jako algoritmus používá zásobník k uložení aktuální cesty a seznam k uložení konečného obvodu. Maximální velikost zásobníku může být v nejhorším případě V + E, takže prostorová složitost je O(V + E).

Vytvořit kvíz

Nejlepší Články

Kategorie

Zajímavé Články