خوارزمية هيرهولزر للرسم البياني الموجه

خوارزمية هيرهولزر للرسم البياني الموجه

بالنظر إلى الرسم البياني الأويليري الموجه، فإن المهمة هي طباعة رسم بياني دائرة أويلر . دائرة أويلر هي مسار يجتاز كل حافة الرسم البياني مرة واحدة بالضبط وينتهي المسار عند قمة البداية.

ملحوظة: يحتوي الرسم البياني المعطى على دائرة أويلر.

مثال:



الإدخال: الرسم البياني الموجه

خوارزمية هيرهولزر للرسم البياني الموجه

الإخراج: 0 3 4 0 2 1 0

المتطلبات الأساسية:

  • لقد ناقشنا مشكلة معرفة ما إذا كان الرسم البياني المعطى هو أويلريان أم لا للحصول على رسم بياني غير موجه
  • شروط دارة أويلريان في Grpag الموجه: (1) تنتمي جميع القمم إلى مكون واحد متصل بقوة. (2) جميع القمم لها نفس الدرجة الداخلية والخارجية. لاحظ أنه بالنسبة للرسم البياني غير الموجه، فإن الحالة مختلفة (جميع القمم لها درجة زوجية)

يقترب:

  1. اختر أي قمة بداية v واتبع مسارًا من الحواف من ذلك الرأس حتى العودة إلى v. ليس من الممكن أن تتعثر في أي قمة بخلاف v لأن الدرجة الداخلية والدرجة الخارجية لكل قمة يجب أن تكون نفسها عندما يدخل المسار إلى قمة أخرى w يجب أن تكون هناك حافة غير مستخدمة تترك w. الجولة التي تم تشكيلها بهذه الطريقة هي جولة مغلقة ولكنها قد لا تغطي جميع القمم والحواف في الرسم البياني الأولي.
  2. طالما أن هناك قمة u تنتمي إلى الجولة الحالية ولكن لها حواف مجاورة ليست جزءًا من الجولة، فابدأ مسارًا آخر منك متبعًا الحواف غير المستخدمة حتى العودة إليك وانضم إلى الجولة التي تم تشكيلها بهذه الطريقة إلى الجولة السابقة.

توضيح:

بأخذ مثال على الرسم البياني أعلاه مع 5 عقد: adj = {{2 3} {0} {1} {4} {0}}.

  1. ابدأ عند القمة 0 :
    • المسار الحالي: [0]
    • الدائرة: []
  2. قمة الرأس 0 → 3 :
    • المسار الحالي: [0 3]
    • الدائرة: []
  3. قمة الرأس 3 → 4 :
    • المسار الحالي: [0 3 4]
    • الدائرة: []
  4. قمة الرأس 4 → 0 :
    • المسار الحالي: [0 3 4 0]
    • الدائرة: []
  5. قمة الرأس 0 → 2 :
    • المسار الحالي: [0 3 4 0 2]
    • الدائرة: []
  6. قمة الرأس 2 → 1 :
    • المسار الحالي: [0 3 4 0 2 1]
    • الدائرة: []
  7. قمة الرأس 1 → 0 :
    • المسار الحالي: [0 3 4 0 2 1 0]
    • الدائرة: []
  8. العودة إلى قمة 0 : أضف 0 إلى الدائرة.
    • المسار الحالي: [0 3 4 0 2 1]
    • الدائرة: [0]
  9. العودة إلى قمة 1 : أضف 1 إلى الدائرة.
    • المسار الحالي: [0 3 4 0 2]
    • الدائرة: [0 1]
  10. العودة إلى قمة 2 : أضف 2 إلى الدائرة.
    • المسار الحالي: [0 3 4 0]
    • الدائرة: [0 1 2]
  11. العودة إلى قمة 0 : أضف 0 إلى الدائرة.
    • المسار الحالي: [0 3 4]
    • الدائرة: [0 1 2 0]
  12. العودة إلى قمة الرأس 4 : أضف 4 إلى الدائرة.
    • المسار الحالي: [0 3]
    • الدائرة: [0 1 2 0 4]
  13. العودة إلى قمة 3 : أضف 3 إلى الدائرة.
    • المسار الحالي: [0]
    • الدائرة: [0 1 2 0 4 3]
  14. العودة إلى قمة 0 : أضف 0 إلى الدائرة.
    • المسار الحالي: []
    • الدائرة: [0 1 2 0 4 3 0]

وفيما يلي تنفيذ النهج المذكور أعلاه: 

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

الإخراج
0 3 4 0 2 1 0  

تعقيد الوقت :  O(V + E) حيث V هو عدد القمم وE هو عدد الحواف في الرسم البياني. والسبب في ذلك هو أن الخوارزمية تقوم بإجراء بحث العمق الأول (DFS) وتزور كل قمة وكل حافة مرة واحدة بالضبط. لذا، فإن كل قمة تستغرق O(1) وقتًا لزيارتها، وتستغرق كل حافة وقتًا O(1) لاجتيازها.

تعقيد المساحة  : O(V + E) حيث تستخدم الخوارزمية مكدسًا لتخزين المسار الحالي وقائمة لتخزين الدائرة النهائية. يمكن أن يكون الحد الأقصى لحجم المكدس V + E في أسوأ الأحوال، وبالتالي يكون تعقيد المساحة هو O(V + E).

إنشاء اختبار

مقالات العلوي

فئة

مقالات مثيرة للاهتمام