बाइनरी ट्री को कौन सा सेल्फ बैलेंस करेगा?


18

मैं हास्केल सीख रहा हूं और एक अभ्यास के रूप में मैं बाइनरी पेड़ बना रहा हूं। एक नियमित बाइनरी ट्री बनाने के बाद, मैं इसे आत्म संतुलन बनाने के लिए अनुकूलित करना चाहता हूं। इसलिए:

  • सबसे कुशल कौन सा है?
  • जिसे लागू करना सबसे आसान है?
  • जो सबसे अधिक बार उपयोग किया जाता है?

लेकिन महत्वपूर्ण रूप से, आप किसे सलाह देते हैं?

मुझे लगता है कि यह यहाँ है क्योंकि यह बहस के लिए खुला है।


कार्यकुशलता और कार्यान्वयन में आसानी के मामले में सामान्य दक्षता अच्छी तरह से परिभाषित है लेकिन आपके कार्यान्वयन के लिए, मुझे लगता है कि सबसे अच्छी बात यह है कि जितना आप पा सकते हैं उतना लागू करें और फिर हमें बताएं जो सबसे अच्छा काम करता है ...
ग्लेनट्रॉन

जवाबों:


15

मैं आपको रेड-ब्लैक ट्री या AVL ट्री के साथ शुरू करने की सलाह दूंगा

लाल-काला पेड़ डालने के लिए तेज़ होता है, लेकिन AVL के पेड़ को देखने के लिए थोड़ी बढ़त होती है। एवीएल पेड़ को लागू करना थोड़ा आसान है, लेकिन मेरे अपने अनुभव के आधार पर इतना नहीं।

एवीएल वृक्ष यह सुनिश्चित करता है कि प्रत्येक डालने या हटाने के बाद पेड़ संतुलित हो (कोई उप-पेड़ का संतुलन कारक 1 / -1 से अधिक न हो, जबकि लाल-काला पेड़ यह सुनिश्चित करता है कि पेड़ किसी भी समय यथोचित संतुलित हो।


1
व्यक्तिगत रूप से, मुझे एवीएल इंसर्ट की तुलना में लाल-काला इंसर्ट आसान लगता है। इसका कारण बी पेड़ों के सादृश्य (अपूर्ण) के माध्यम से है। सम्मिलित रूप से काल्पनिक हैं, लेकिन हटाए गए बुराई हैं (इसलिए कई मामलों पर विचार करने के लिए)। वास्तव में मेरे पास अब अपना स्वयं का C ++ लाल-काला हटाने वाला कार्यान्वयन नहीं है - जब मैंने महसूस किया कि मैंने इसे हटा दिया है (1) मैं कभी भी इसका उपयोग नहीं कर रहा था - हर बार जब मैं हटाना चाहता था तो मैं कई वस्तुओं को हटा रहा था, इसलिए मैं पेड़ से परिवर्तित हो गया सूची, सूची से हटाएं, फिर एक पेड़ में परिवर्तित करें, और (2) यह वैसे भी टूट गया था।
स्टीव ३१

2
@ स्टीव 314, लाल-काले पेड़ आसान हैं, लेकिन आप एक कार्यान्वयन करने में सक्षम नहीं हैं जो काम करता है? AVL के पेड़ क्या हैं?
dan_waterworth

@dan_waterworth - मैंने एक इंसर्ट विधि के साथ भी कार्यान्वयन नहीं किया है जो अभी तक काम करता है - नोट्स हैं, मूल सिद्धांत को समझते हैं, लेकिन प्रेरणा, समय और आत्मविश्वास का सही संयोजन कभी नहीं मिला। अगर मुझे ऐसे संस्करण चाहिए थे जो काम करते हैं, तो यह सिर्फ कॉपी-स्यूडोकोड-से-टेक्स्टबुक-एंड-ट्रांसलेशन है (और सी ++ को मत भूलना मानक लाइब्रेरी कंटेनर हैं), लेकिन इसमें मज़ा कहाँ है?
स्टीव ३१

BTW - मेरा मानना ​​है (लेकिन संदर्भ प्रदान नहीं कर सकते) कि एक काफी लोकप्रिय पाठ्यपुस्तक में संतुलित बाइनरी ट्री एल्गोरिदम में से एक का एक छोटी गाड़ी कार्यान्वयन शामिल है - सुनिश्चित नहीं है, लेकिन यह लाल-काला हटाना हो सकता है। तो यह सिर्फ मैं ;-)
स्टीव 314

1
@ स्टीव ३१४, मुझे पता है, पेड़ अनिवार्य रूप से अनिवार्य भाषा में जटिल हो सकते हैं, लेकिन आश्चर्यजनक रूप से, हास्केल में उन्हें लागू करना एक हवा है। मैंने एक नियमित AVL पेड़ लिखा है और सप्ताहांत में 1D स्थानिक संस्करण भी है और वे दोनों केवल लगभग 60 लाइनें हैं।
dan_waterworth

10

यदि आप यादृच्छिक डेटा संरचनाओं के साथ ठीक हैं तो मैं एक विकल्प पर विचार करूंगा : सूचियां छोड़ें

एक उच्च-स्तरीय दृष्टिकोण से, यह एक पेड़ की संरचना है, सिवाय इसके कि इसे एक पेड़ के रूप में लागू नहीं किया गया है, लेकिन लिंक की कई परतों के साथ एक सूची के रूप में।

आपको O (लॉग एन) सम्मिलन / खोजें / डिलीट मिलेंगे, और आपको उन सभी मुश्किलों से निपटने के मामलों से निपटना नहीं पड़ेगा।

मैंने उन्हें एक कार्यात्मक भाषा में लागू करने पर कभी विचार नहीं किया है, और विकिपीडिया पृष्ठ कोई भी नहीं दिखाता है, इसलिए यह आसान नहीं हो सकता है (अपरिपक्वता के कारण)


मैं वास्तव में स्किप सूचियों का आनंद लेता हूं और मैंने उन्हें पहले लागू किया है, हालांकि एक कार्यात्मक भाषा में नहीं। मुझे लगता है कि मैं इसके बाद उनका प्रयास करूंगा, लेकिन अभी मैं स्व-संतुलन वाले पेड़ों पर हूं।
dan_waterworth

इसके अलावा, लोग अक्सर समवर्ती डेटा संरचनाओं के लिए स्किप्पिस्ट का उपयोग करते हैं। यह बेहतर हो सकता है कि अपरिवर्तनीयता को मजबूर करने के बजाय, हैसेल के संगामिति आदिम (जैसे एमवीएआर या टीवीर) का उपयोग करें। हालाँकि, यह मुझे कार्यात्मक कोड लिखने के बारे में बहुत कुछ नहीं सिखाएगा।
dan_waterworth

2
@ Fanatic23, एक स्किप सूची एक ADT नहीं है। ADT या तो एक सेट या एक सहयोगी सरणी है।
dan_waterworth

@dan_waterworth मेरा बुरा, आप सही हैं।
Fanatic23

5

यदि आप अपेक्षाकृत आसान संरचना शुरू करना चाहते हैं (दोनों AVL पेड़ों और लाल-काले पेड़ों के बीच में हैं), तो एक विकल्प एक ट्रीपप है - जिसे "ट्री" और "हीप" के संयोजन के रूप में नामित किया गया है।

प्रत्येक नोड को एक "प्राथमिकता" मान मिलता है, अक्सर नोड बनाए जाने के दौरान यादृच्छिक रूप से असाइन किया जाता है। पेड़ को नोड्स में तैनात किया जाता है ताकि महत्वपूर्ण आदेश का सम्मान किया जा सके, और इसलिए कि प्राथमिकता के मूल्यों के ढेर की तरह आदेश का सम्मान किया जाता है। हीप जैसे ऑर्डर का मतलब है कि माता-पिता के दोनों बच्चों की प्राथमिकता माता-पिता की तुलना में कम है।

EDIT ने "प्रमुख मूल्यों के भीतर" को हटा दिया - प्राथमिकता और कुंजी क्रम एक साथ लागू होते हैं, इसलिए अद्वितीय कुंजियों के लिए भी प्राथमिकता महत्वपूर्ण है।

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


1
+1। Treaps मेरी निजी पसंद है, मैंने भी एक ब्लॉग पोस्ट लिखा है कि वे कैसे लागू होते हैं।
पी शेव्ड

5

सबसे कुशल कौन सा है?

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

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

जिसे लागू करना सबसे आसान है?

अस्पष्ट और जवाब देने में मुश्किल। कुछ एल्गोरिदम आपके लिए जटिल हो सकते हैं, लेकिन मेरे लिए तुच्छ हैं।

जो सबसे अधिक बार उपयोग किया जाता है?

अस्पष्ट और जवाब देने में मुश्किल। पहले वहाँ "किसके द्वारा?" इस का हिस्सा? हास्केल ही? C या C ++ के बारे में क्या? दूसरा, मालिकाना सॉफ्टवेयर समस्या है जहां हमारे पास सर्वेक्षण करने के लिए स्रोत तक पहुंच नहीं है।

लेकिन महत्वपूर्ण रूप से, आप किसे सलाह देते हैं?

मुझे लगता है कि यह यहाँ है क्योंकि यह बहस के लिए खुला है।

सही बात। चूँकि आपके अन्य मानदंड बहुत सहायक नहीं हैं, इसलिए आप इसे प्राप्त करने जा रहे हैं।

आप बड़ी संख्या में ट्री एल्गोरिदम के लिए स्रोत प्राप्त कर सकते हैं। यदि आप कुछ सीखना चाहते हैं, तो आप बस हर एक को लागू कर सकते हैं जिसे आप पा सकते हैं। एक "सिफारिश" के लिए पूछने के बजाय, बस हर एल्गोरिदम को इकट्ठा करें जो आप पा सकते हैं।

यहाँ सूची है:

http://en.wikipedia.org/wiki/Self-balancing_binary_search_tree

वहाँ छह लोकप्रिय परिभाषित कर रहे हैं। उन लोगों के साथ शुरू करो।


3

यदि आप Splay के पेड़ों में रुचि रखते हैं, तो उन लोगों का एक सरल संस्करण है जो मुझे लगता है कि पहली बार एलन और मुनरो द्वारा एक पेपर में वर्णित किया गया था। इसमें समान प्रदर्शन की गारंटी नहीं है, लेकिन "ज़िग-ज़िग" बनाम "ज़िग-ज़ैग" असंतुलन से निपटने में जटिलताओं से बचा जाता है।

मूल रूप से, जब खोज (एक सम्मिलित बिंदु या हटाने के लिए नोड सहित खोज), तो नोड आपको लगता है कि सीधे रूट की ओर घुमाया जाता है, नीचे ऊपर (उदाहरण के लिए पुनरावर्ती खोज फ़ंक्शन से बाहर निकलता है)। प्रत्येक चरण में, आप एक एकल बाएं या दाएं रोटेशन का चयन करते हैं, इस पर निर्भर करता है कि आप जिस बच्चे को जड़ की ओर एक और कदम खींचना चाहते हैं, वह सही बच्चा या बाएं बच्चा था (यदि मुझे अपने रोटेशन के निर्देशों को सही ढंग से याद है, तो वह क्रमशः है)।

सेपले पेड़ों की तरह, विचार यह है कि हाल ही में एक्सेस किए गए आइटम हमेशा पेड़ की जड़ के पास होते हैं, इसलिए फिर से पहुंचने के लिए जल्दी। सरल होने के नाते, ये एलन-मुनरो घुमाए जाने वाले पेड़ (मैं उन्हें क्या कहता हूं - आधिकारिक नाम नहीं जानता) तेज हो सकता है, लेकिन उनके पास समान परिशोधन प्रदर्शन की गारंटी नहीं है।

एक बात - चूंकि यह डेटा संरचना परिभाषा कार्यों के लिए भी उत्परिवर्तित करती है, इसलिए इसे संभवतः वैचारिक रूप से लागू करने की आवश्यकता होगी। IOW यह कार्यात्मक प्रोग्रामिंग के लिए एक अच्छा फिट नहीं है।


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

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

न तो दृष्टिकोण के प्रयास के लायक लगता है। फिर, न तो अधिकांश भाग के लिए विशुद्ध रूप से कार्यात्मक भाषाएं।
क्विक जो स्मिथ

1
@ क्विक - ट्री को डुप्लिकेट करना आप आवेषण जैसे एल्गोरिदम को म्यूट करने के लिए शुद्ध कार्यात्मक भाषा में किसी भी ट्री डेटा संरचना के लिए करेंगे। स्रोत के संदर्भ में, यह कोड उस स्थान से अलग नहीं होगा जो इन-प्लेस अपडेट करता है। असंतुलित बाइनरी पेड़ों के लिए मतभेद पहले से ही संभाले हुए हैं। जब तक आप मूल लिंक को नोड्स में जोड़ने का प्रयास नहीं करते हैं, तब तक डुप्लिकेट सामान्य सबट्रेम्स को कम से कम साझा करेगा, और हास्केल में गहरी अनुकूलन बहुत ही कट्टर है अगर सही नहीं है। मैं सिद्धांत रूप में अपने आप में हास्केल विरोधी हूं, लेकिन यह जरूरी नहीं कि एक समस्या हो।
स्टीव ३१

2

एक बहुत ही सरल संतुलित वृक्ष एक AA वृक्ष है । यह अपरिवर्तनशील है और इस प्रकार यह आसान है। अपनी सादगी के कारण, इसका प्रदर्शन अभी भी अच्छा है।

एक उन्नत अभ्यास के रूप में, आप संतुलित वृक्षों के वेरिएंट को लागू करने के लिए GADTs का उपयोग करने का प्रयास कर सकते हैं, जिसका इनवेरिएंट टाइप सिस्टम प्रकार द्वारा लागू किया जाता है।

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