ग्राफ़ में चक्र खोजने के लिए डीएफएस और बीएफएस क्यों नहीं


85

मुख्य रूप से DFS का उपयोग ग्राफ़ में एक चक्र खोजने के लिए किया जाता है न कि BFS में। कोई कारण? दोनों पा सकते हैं कि क्या पेड़ / ग्राफ को पार करते समय एक नोड पहले ही आ चुका है।


5
निर्देशित रेखांकन में, केवल एक चक्र का पता लगाने के लिए डीएफएस का उपयोग किया जा सकता है; लेकिन अप्रत्यक्ष रेखांकन में दोनों का उपयोग किया जा सकता है।
हेंगामेह

जवाबों:


73

गहराई पहली खोज अधिक याददाश्त से भरी हुई है, जो पहली खोज है क्योंकि आप जल्द ही पीछे हट सकते हैं। यदि आप कॉल स्टैक का उपयोग करते हैं तो इसे लागू करना भी आसान है लेकिन यह सबसे लंबे पथ पर निर्भर करता है जो स्टैक से अधिक नहीं बहता है।

इसके अलावा यदि आपका ग्राफ निर्देशित है तो आपको यह याद नहीं रखना है कि आप नोड पर गए हैं या नहीं, बल्कि यह भी कि आपको वहां कैसे जाना है। अन्यथा आप सोच सकते हैं कि आपको एक चक्र मिल गया है लेकिन वास्तव में आपके पास दो अलग-अलग रास्ते हैं A-> B लेकिन इसका मतलब यह नहीं है कि एक रास्ता B-> A है। उदाहरण के लिए,

यदि आप BFS से शुरू करते हैं 0, तो यह पता लगाएगा कि चक्र मौजूद है लेकिन वास्तव में कोई चक्र नहीं है।

गहराई से पहले खोज के साथ आप नोड्स को चिह्नित कर सकते हैं जैसा कि आप नीचे उतरते हैं और उन्हें पीछे की तरफ चिह्नित करते हैं। इस एल्गोरिथ्म के प्रदर्शन में सुधार के लिए टिप्पणियां देखें।

के लिए एक निर्देशित ग्राफ में चक्र का पता लगाने के लिए सबसे अच्छा एल्गोरिथ्म अपने आप को देखो सकता है Tarjan एल्गोरिथ्म


3
(मेमोरी कुशल, क्योंकि आप जल्द ही पीछे हट जाते हैं, और लागू करने में आसान होते हैं क्योंकि आप स्टैक को केवल स्पष्ट रूप से बनाए रखने के बजाय खुली सूची को संग्रहीत करने का ध्यान रख सकते हैं।)
एम्बर

3
IMO, यह केवल तभी आसान है जब आप पूंछ पुनरावृत्ति पर भरोसा कर सकते हैं।
हांक गे

2
"उन्हें अपने पीछे के निशान के रूप में चिह्नित करें" - अपने स्वयं के जोखिम पर! यह आसानी से O (n ^ 2) व्यवहार को जन्म दे सकता है, विशेष रूप से इस तरह के डीएफएस किनारों को "पेड़" किनारों के रूप में गलत समझेगा ("पेड़" किनारे भी एक मिथ्या नाम होगा क्योंकि वे वास्तव में अब एक पेड़ नहीं
बनाएंगे

1
@ डमिट्रिस आंद्रेओ: प्रदर्शन सुधारने के लिए आप दो के बजाय तीन विज़िट किए गए राज्यों का उपयोग कर सकते हैं। निर्देशित ग्राफ़ के साथ 'मैंने इस नोड को पहले देखा है' और 'यह नोड एक लूप का हिस्सा है' के बीच अंतर है। अप्रत्यक्ष रेखांकन के साथ वे समतुल्य हैं।
मार्क बायर्स

वास्तव में, आपको निश्चित रूप से एक तीसरी स्थिति (एल्गोरिथ्म को रैखिक बनाने के लिए) की आवश्यकता है, इसलिए आपको उस हिस्से को संशोधित करने पर विचार करना चाहिए।
दिमित्रिस आंद्रेउ

28
  1. डीएफएस को लागू करना आसान है
  2. एक बार डीएफएस को एक चक्र मिल जाता है, तो स्टैक में चक्र बनाने वाले नोड्स होंगे। बीएफएस के लिए भी यह सच नहीं है, इसलिए यदि आप अतिरिक्त चक्र को प्रिंट करना चाहते हैं तो आपको अतिरिक्त काम करने की आवश्यकता है। यह DFS को और अधिक सुविधाजनक बनाता है।

10

यदि ग्राफ़ अप्रत्यक्ष है तो BFS उचित हो सकता है (BFS का उपयोग करके एक कुशल एल्गोरिथ्म दिखाने में मेरे अतिथि बनें जो कि एक निर्देशित ग्राफ़ में चक्रों की रिपोर्ट करेगा!), जहां प्रत्येक "क्रॉस एज" एक चक्र को परिभाषित करता है। यदि क्रॉस एज है {v1, v2}, और रूट (BFS ट्री में) जिसमें वो नोड्स हैं r, तो साइकल r ~ v1 - v2 ~ r( ~एक रास्ता है, -सिंगल एज), जिसे लगभग DFS की तरह ही आसानी से रिपोर्ट किया जा सकता है।

बीएफएस का उपयोग करने का एकमात्र कारण यह होगा कि यदि आप जानते हैं कि आपका (अप्रत्यक्ष) ग्राफ लंबा पथ और छोटा पथ कवर है (दूसरे शब्दों में, गहरे और संकीर्ण)। उस स्थिति में, BFS को DFS के स्टैक की तुलना में अपनी कतार के लिए आनुपातिक रूप से कम मेमोरी की आवश्यकता होगी (दोनों अभी भी रैखिक हैं)।

अन्य सभी मामलों में, DFS स्पष्ट रूप से विजेता है। यह निर्देशित और अप्रत्यक्ष दोनों तरह के रेखांकन पर काम करता है, और यह चक्रों की रिपोर्ट करने के लिए तुच्छ है - पूर्वजों से वंश तक के रास्ते में किसी भी पीछे के किनारे को संक्षिप्त करें, और आपको चक्र मिलता है। सभी में, इस समस्या के लिए बीएफएस की तुलना में बहुत बेहतर और व्यावहारिक है।


4

BFS साइकिल खोजने में एक निर्देशित ग्राफ के लिए काम नहीं करेगा। एक ग्राफ में A- B से पथ के रूप में A-> B और A-> C-> B पर विचार करें। बीएफएस कहेंगे कि बी के एक पथ के साथ जाने के बाद। अगले पथ की यात्रा जारी रखने पर यह कहेगा कि चिह्नित नोड बी फिर से मिल गया है, इसलिए, एक चक्र है। स्पष्ट रूप से यहाँ कोई चक्र नहीं है।


क्या आप बता सकते हैं कि डीएफएस स्पष्ट रूप से उस चक्र की पहचान कैसे करेगा, जो आपके उदाहरण में मौजूद नहीं है। मैं सहमत हूं कि चक्र उदाहरण में मौजूद नहीं है। लेकिन अगर हम A-> B से जाते हैं और फिर A-> C-> B हम पाएंगे उस बी को पहले से ही देखा गया था और उसके माता-पिता ए नहीं सी हैं..और मैंने पढ़ा कि डीएफएस चक्र का पता लगाएगा कि पहले से ही दौरा किए गए तत्व के माता-पिता की तुलना वर्तमान नोड के साथ किस दिशा से हो रही है। हम इस समय डीएफएस गलत कर रहे हैं या क्या?
कड़ी चोट

आपको यहां दिखाया गया है कि यह विशेष कार्यान्वयन काम नहीं करता है, ऐसा नहीं है कि यह बीएफएस के साथ असंभव है। वास्तव में, यह है संभव है, हालांकि यह अधिक काम और अंतरिक्ष ले जाता है।
प्र्यून

@Prune: यहाँ सभी थ्रेड्स (i थिंक) यह साबित करने की कोशिश कर रहे हैं कि bfs चक्र का पता लगाने के लिए काम नहीं करेंगे। यदि आप जानते हैं कि कैसे साबित करने के लिए आपको प्रमाण देना चाहिए। केवल यह कहते हुए कि प्रयास अधिक नहीं हैं
आदित्य रमन

चूंकि एल्गोरिथ्म लिंक्ड पोस्टिंग में दिया गया है, इसलिए मुझे यहां रूपरेखा को दोहराना उचित नहीं लगता।
प्रून

मुझे कोई भी लिंकिंग पोस्टिंग नहीं मिली, इसलिए उसी के लिए कहा गया। मैं बीएफएस क्षमता के बारे में आपकी बात से सहमत हूं और कार्यान्वयन के बारे में अभी सोचा है। टिप के लिए धन्यवाद :)
आदित्य रमन

3

मुझे नहीं पता कि इस तरह के पुराने सवाल मेरे फीड में क्यों आए, लेकिन पिछले सभी उत्तर खराब हैं, इसलिए ...

डीएफएस का उपयोग निर्देशित ग्राफ़ में चक्र खोजने के लिए किया जाता है, क्योंकि यह काम करता है

डीएफएस में, प्रत्येक शीर्ष को "विज़िट" किया जाता है, जहां एक शीर्ष पर जाने का अर्थ है:

  1. शीर्षासन शुरू किया जाता है
  2. उस शीर्ष से आने वाले सबग्राफ का दौरा किया जाता है। इसमें सभी अपरिवर्तित किनारों को ट्रेस करना शामिल है, जो उस शीर्ष से पुन: प्राप्य हैं, और सभी पहुंच से बाहर के अपरिवर्तित शीर्षों पर जाएँ।

  3. शिखर समाप्त हो गया है।

महत्वपूर्ण विशेषता यह है कि एक शीर्ष से पहुंचने वाले सभी किनारों का पता लगाया जाता है, जब शीर्ष समाप्त होने से पहले। यह डीएफएस की एक विशेषता है, लेकिन बीएफएस नहीं। वास्तव में यह डीएफएस की परिभाषा है।

इस विशेषता के कारण, हम जानते हैं कि एक चक्र में पहला शीर्ष कब शुरू होता है:

  1. चक्र के किसी भी किनारे का पता नहीं लगाया गया है। हम यह जानते हैं, क्योंकि आप केवल चक्र में एक और शीर्ष से उन्हें प्राप्त कर सकते हैं, और हम शुरू होने वाले पहले शीर्ष के बारे में बात कर रहे हैं ।
  2. उस शीर्ष से आने वाले सभी अछूते किनारों को समाप्त होने से पहले पता लगाया जाएगा, और इसमें चक्र के सभी किनारों को शामिल किया गया है, क्योंकि उनमें से कोई भी अभी तक पता नहीं लगाया गया है। इसलिए, यदि कोई चक्र है, तो हम इसे शुरू करने के बाद पहले शीर्ष पर वापस किनारे पाएंगे, लेकिन इससे पहले कि यह समाप्त हो जाए; तथा
  3. चूंकि सभी किनारों का पता लगाया जाता है, जो कि हर शुरू-लेकिन-अपूर्ण वर्टेक्स से उपलब्ध होते हैं, इस तरह के वर्टेक्स के लिए एक किनारे को ढूंढना हमेशा एक चक्र को इंगित करता है।

इसलिए, यदि कोई चक्र है, तो हम शुरू-लेकिन-अपूर्ण वर्टेक्स (2) के लिए एक किनारे खोजने की गारंटी देते हैं, और अगर हमें ऐसी कोई बढ़त मिलती है, तो हम गारंटी देते हैं कि एक चक्र (3) है।

यही कारण है कि डीएफएस का उपयोग निर्देशित ग्राफ़ में चक्र खोजने के लिए किया जाता है।

BFS ऐसी कोई गारंटी नहीं देता है, इसलिए यह काम नहीं करता है। (बीएफएस या एक उप-प्रक्रिया के समान शामिल होने वाले पूरी तरह से अच्छे चक्र-खोज एल्गोरिदम के बावजूद)

एक अप्रत्यक्ष ग्राफ, दूसरी ओर, एक चक्र होता है जब भी किसी भी जोड़ी के शीर्षों के बीच दो रास्ते होते हैं, अर्थात, जब यह एक पेड़ नहीं होता है। बीएफएस या डीएफएस के दौरान यह पता लगाना आसान है - नए शीर्षों के लिए खोजे गए किनारे एक पेड़ बनाते हैं, और किसी भी अन्य किनारे से एक चक्र का संकेत मिलता है।


वास्तव में, यह वास्तविक कारणों पर विस्तृत रूप से यहां (शायद एकमात्र) संबंधित उत्तर है।
प्लाज़्मासेल

2

यदि आप एक पेड़ पर एक यादृच्छिक स्थान पर एक चक्र लगाते हैं, तो डीएफएस चक्र को हिट करेगा जब यह लगभग आधे पेड़ को कवर करेगा, और आधे समय में यह पहले से ही पता लगाया जाएगा कि चक्र कहां जाता है, और आधा समय ऐसा नहीं होगा ( और यह पेड़ के बाकी हिस्सों में औसतन पाया जाएगा), इसलिए यह पेड़ के औसतन 0.5 * 0.5 + 0.5 * 0.75 = 0.625 का मूल्यांकन करेगा।

यदि आप एक पेड़ पर एक यादृच्छिक स्थान पर एक चक्र लगाते हैं, तो BFS उस चक्र को केवल तभी हिट करेगा जब उस गहराई पर पेड़ की परत का मूल्यांकन किया जाएगा। इस प्रकार, आप आमतौर पर एक संतुलन बाइनरी ट्री की पत्तियों का मूल्यांकन करने के लिए समाप्त होते हैं, जिसके परिणामस्वरूप आमतौर पर पेड़ का अधिक मूल्यांकन होता है। विशेष रूप से, 3/4 समय में कम से कम दो में से एक लिंक पेड़ की पत्तियों में दिखाई देता है, और उन मामलों पर आपको पेड़ के औसत 3/4 पर मूल्यांकन करना होगा (यदि एक लिंक है) या 7 / पेड़ के 8 (यदि दो हैं), तो आप पहले से ही 1/2 * 3/4 ​​+ 1/4 * 7/8 = (7 + 12) / 32 = 21/32 = की खोज की उम्मीद पर कायम हैं 0.656 ... पेड़ की खोज के बिना एक चक्र के साथ एक पेड़ की खोज की लागत को जोड़ने के अलावा पत्ती नोड्स से दूर हो गया।

इसके अलावा, डीएफएस बीएफएस की तुलना में लागू करना आसान है। इसलिए यह तब तक उपयोग करने वाला है जब तक आप अपने चक्रों के बारे में कुछ नहीं जानते हैं (उदाहरण के लिए, चक्र की जड़ के पास होने की संभावना है जहां से आप खोजते हैं, जिस बिंदु पर BFS आपको लाभ देता है)।


वहाँ बहुत सारे जादू नंबर। मैं "डीएफएस तेज है" तर्कों से असहमत हूं। यह पूरी तरह से इनपुट पर निर्भर करता है, और कोई भी इनपुट इस मामले में दूसरे से ज्यादा सामान्य नहीं है।
इवलाद

@ व्लाद - संख्याएं जादू नहीं हैं। वे साधन हैं, इस तरह के रूप में कहा जाता है, और मेरे द्वारा बताई गई मान्यताओं की गणना करने के लिए लगभग तुच्छ हैं। यदि माध्य द्वारा सन्निकटन एक बुरा सन्निकटन है, तो यह एक वैध आलोचना होगी। (और मैंने स्पष्ट रूप से कहा कि यदि आप संरचना के बारे में धारणा बना सकते हैं, तो उत्तर बदल सकता है।)
रेक्स केर

संख्याएं जादुई हैं क्योंकि उनका कोई मतलब नहीं है। आपने एक ऐसा मामला लिया जिसमें डीएफएस बेहतर है और उन परिणामों को सामान्य मामले में हटा दिया है। आपके कथन निराधार हैं: "डीएफएस चक्र को हिट करेगा जब यह लगभग आधे पेड़ से ढंका होगा": इसे साबित करें। यह उल्लेख करने के लिए कि आप एक पेड़ में चक्रों के बारे में बात नहीं कर सकते। एक पेड़ में परिभाषा के अनुसार एक चक्र नहीं होता है। मैं सिर्फ यह नहीं देखता कि आपकी बात क्या है। डीएफएस एक रास्ता तब तक चलेगा जब तक कि यह एक मृत अंत नहीं हो जाता है, इसलिए आपके पास यह जानने का कोई तरीका नहीं है कि यह औसत रूप से कितना GRAPH (पेड़ नहीं) है। आपने सिर्फ एक यादृच्छिक मामला उठाया है जो कुछ भी साबित नहीं करता है।
IVlad

@ व्लाद - सभी गैर-चक्रीय पूरी तरह से जुड़े अप्रत्यक्ष रेखांकन (अप्रकाशित अप्रत्यक्ष) पेड़ हैं। मेरा मतलब था "एक ग्राफ जो एक पेड़ के लिए एक शानदार कड़ी के लिए बचा होगा"। शायद यह एल्गोरिथ्म के लिए मुख्य अनुप्रयोग नहीं है - शायद आप कुछ पेचीदा ग्राफ में चक्र ढूंढना चाहते हैं जिसमें बहुत सारे लिंक हैं जो इसे एक पेड़ नहीं बनाते हैं। लेकिन अगर यह ट्री-लाइक है, तो सभी ग्राफ़ पर औसतन, किसी भी नोड को उतनी ही सहज लिंक के स्रोत होने की संभावना है, जो लिंक हिट होने पर अपेक्षित ट्री कवरेज को 50% बनाता है। इसलिए मैं स्वीकार करता हूं कि उदाहरण प्रतिनिधि नहीं हो सकता है। लेकिन गणित तुच्छ होना चाहिए।
रेक्स केर

1

यह साबित करने के लिए कि एक ग्राफ चक्रीय है, आपको सिर्फ यह साबित करने की जरूरत है कि इसका एक चक्र है (सीधे या परोक्ष रूप से खुद की ओर इशारा करते हुए)।

डीएफएस में हम एक बार में एक शीर्ष लेते हैं और जांचते हैं कि क्या यह चक्र है। जैसे ही एक चक्र मिलता है हम अन्य कोने की जाँच को छोड़ सकते हैं।

बीएफएस में हमें कई वर्टेक्स किनारों को एक साथ रखने की आवश्यकता होती है और अधिक बार अंत में आपको पता नहीं चलता है कि क्या यह चक्र है। जैसे-जैसे ग्राफ का आकार बढ़ता है, DFS की तुलना में BFS को अधिक स्थान, संगणना और समय की आवश्यकता होती है।


0

यह निर्भर करता है कि क्या आप पुनरावर्ती या पुनरावृत्त कार्यान्वयन के बारे में बात कर रहे हैं।

रिकर्सिव-डीएफएस हर नोड पर दो बार जाता है। Iterative-BFS प्रत्येक नोड पर एक बार जाता है।

यदि आप एक चक्र का पता लगाना चाहते हैं, तो आपको नोड से पहले और उसके बाद दोनों नोड्स की जांच करने की आवश्यकता है - जब आप नोड पर "शुरू" करते हैं और जब आप नोड के साथ "समाप्त" करते हैं।

इसके लिए Iterative-BFS में अधिक कार्य की आवश्यकता होती है, इसलिए अधिकांश लोग Recursive-DFS चुनते हैं।

ध्यान दें कि, के साथ Iterative-DFS का एक सरल कार्यान्वयन, std :: stack में Iterative-BFS जैसी ही समस्या है। उस स्थिति में, आपको नोड पर काम करने के दौरान डमी तत्वों को ट्रैक करने के लिए स्टैक में रखना होगा।

Iterative-DFS को नोड के साथ "समाप्त" करने के लिए यह निर्धारित करने के लिए अतिरिक्त कार्य की आवश्यकता है कि कैसे (TopoSort के संदर्भ में जवाब दिया गया है):

पुनरावृत्ति के बिना डीएफएस का उपयोग कर सामयिक प्रकार

उम्मीद है कि यह बताता है कि लोग उन समस्याओं के लिए पुनरावर्ती-डीएफएस का पक्ष क्यों लेते हैं, जहां आपको यह निर्धारित करने की आवश्यकता होती है कि आप नोड को संसाधित करते समय "खत्म" करते हैं।


यह पूरी तरह से गलत है, क्योंकि इससे कोई फर्क नहीं पड़ता कि आप पुनरावृत्ति का उपयोग करते हैं या आप पुनरावृत्ति को पुन: समाप्त करते हैं। आप एक पुनरावृत्त डीएफएस को लागू कर सकते हैं जो प्रत्येक नोड पर दो बार आता है, जैसे आप एक पुनरावर्ती संस्करण को लागू कर सकते हैं जो प्रत्येक नोड पर केवल एक बार आता है।
प्लाज़्मासेल

0

BFSजब आप किसी दिए गए नोड में एक निर्देशित ग्राफ में सबसे छोटा चक्र ढूंढना चाहते हैं तो आपको इसका उपयोग करना होगा।

उदाहरण के लिए:यहां छवि विवरण दर्ज करें

यदि दिए गए नोड 2 हैं, तो तीन चक्र हैं जहां यह - [2,3,4], [2,3,4,5,6,7,8,9]& का हिस्सा है [2,5,6,7,8,9]। सबसे छोटा है[2,3,4]

बीएफएस का उपयोग करके इसे लागू करने के लिए, आपको उचित डेटा संरचनाओं का उपयोग करके विज़िट किए गए नोड्स के इतिहास को स्पष्ट रूप से बनाए रखना होगा।

लेकिन अन्य सभी उद्देश्यों के लिए (उदाहरण के लिए: किसी भी चक्रीय पथ को खोजने के लिए या यह जांचने के लिए कि क्या कोई चक्र मौजूद है या नहीं), DFSदूसरों द्वारा उल्लिखित कारणों के लिए स्पष्ट विकल्प है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.