क्या द्विआधारी खोज पेड़ों की परिभाषा में डुप्लिकेट कुंजियों की अनुमति है?


139

मैं बाइनरी सर्च ट्री की परिभाषा खोजने की कोशिश कर रहा हूं और मुझे हर जगह अलग-अलग परिभाषाएं मिल रही हैं।

कुछ का कहना है कि किसी भी सबट्री के लिए बाएं बच्चे की चाबी जड़ से कम या बराबर होती है।

कुछ का कहना है कि किसी भी सबट्री के लिए सही चाइल्ड कीज़ रूट से अधिक या उसके बराबर है।

और मेरी पुरानी कॉलेज डेटा स्ट्रक्चर्स बुक कहती है, "प्रत्येक तत्व में एक कुंजी है और किसी भी दो तत्वों के पास समान कुंजी नहीं है।"

क्या bst की एक सार्वभौमिक परिभाषा है? विशेष रूप से एक ही कुंजी के कई उदाहरणों के साथ पेड़ों के साथ क्या करना है के संबंध में।

संपादित करें: शायद मैं अस्पष्ट था, जो परिभाषाएं मैं देख रहा हूं वे हैं

1) बायां <= जड़ <दायां

2) बायां <रूट <= दायां

3) बायां <रूट <सही, ऐसा है कि कोई डुप्लिकेट कुंजी मौजूद नहीं है।

जवाबों:


78

कई एल्गोरिदम निर्दिष्ट करेंगे कि डुप्लिकेट को बाहर रखा गया है। उदाहरण के लिए, एमआईटी एल्गोरिदम पुस्तक में उदाहरण एल्गोरिदम आमतौर पर डुप्लिकेट के बिना उदाहरण प्रस्तुत करते हैं। यह डुप्लिकेट को लागू करने के लिए काफी तुच्छ है (या तो नोड पर एक सूची के रूप में, या एक विशेष दिशा में।)

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

डुप्लिकेट को स्टोर करने के लिए नोड पर एक सूची का उपयोग करना सबसे अच्छा है, क्योंकि नोड के एक तरफ '=' मान डालने के लिए उस तरफ के पेड़ को फिर से लिखना होगा ताकि नोड को बच्चे के रूप में रखा जा सके, या नोड को एक भव्य के रूप में रखा जाए। -बच्चों, नीचे कुछ बिंदु पर, जो खोज दक्षता में से कुछ को समाप्त करता है।

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

तो अपने डेटा संरचनाओं पुस्तक क्या कहा के साथ जाओ!

संपादित करें:

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

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


1
नोड पर एक सूची का उपयोग करने के नुकसान क्या हैं?
पचेरियर

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

50

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

बाएं <रूट <= दाएं

अब एक साधारण पेड़ की कल्पना करें जिसकी जड़ 5 है, बायां बच्चा शून्य है, और दायां बच्चा 5 है। यदि आप जड़ पर बाएं घूमते हैं तो आप बाएं बच्चे में 5 और दाएं बच्चे के साथ जड़ में 5 शून्य हो रहा है। अब बाएं पेड़ में कुछ जड़ के बराबर है, लेकिन ऊपर दिए गए आपके नियम को छोड़ दिया गया है <जड़।

मैंने घंटों यह जानने की कोशिश की कि मेरे लाल / काले पेड़ कभी-कभार बाहर क्यों आएँगे, समस्या यह है कि मैंने ऊपर वर्णित किया था। उम्मीद है कि कोई इसे पढ़ता है और भविष्य में खुद को डीबग करने के घंटे बचाता है!


18
जब आपके पास समान नोड्स हों तो घुमाएँ नहीं! अगले स्तर तक नीचे की ओर ले जाएं और उसे घुमाएं।
रिच

2
अन्य समाधान या तो पेड़ के नियम को बदलने के लिए हैं left <= node <= right, या केवल मूल्य की पहली घटना से पहले डालें ।
paxdiablo

व्यवहार में इसके कारण क्या समस्याएं हो सकती हैं? मुझे लगता है कि यदि आप बाएं <= नोड <= दाएं के साथ ठीक हैं, तो सभी लाल-काले पेड़ों के संचालन किसी भी तरह से काम करेंगे।
ब्योर्न लिंडक्विस्ट

39

सभी तीन परिभाषाएँ स्वीकार्य और सही हैं। वे एक BST के विभिन्न रूपों को परिभाषित करते हैं।

आपके कॉलेज डेटा संरचना की पुस्तक यह स्पष्ट करने में विफल रही कि इसकी परिभाषा केवल संभव नहीं थी।

निश्चित रूप से, डुप्लिकेट को अनुमति देना जटिलता जोड़ता है। यदि आप "बाएं <= रूट <सही" परिभाषा का उपयोग करते हैं और आपके पास एक पेड़ है:

      3
    /   \
  2       4

फिर इस पेड़ में "3" डुप्लिकेट कुंजी जोड़ने से परिणाम होगा:

      3
    /   \
  2       4
    \
     3

ध्यान दें कि डुप्लिकेट सन्निहित स्तरों में नहीं हैं।

यह एक बड़ा मुद्दा है जब एक BST प्रतिनिधित्व में डुप्लिकेट को उपरोक्त के रूप में अनुमति देता है: डुप्लिकेट को किसी भी स्तर के स्तर से अलग किया जा सकता है, इसलिए डुप्लिकेट के अस्तित्व की जाँच करना इतना आसान नहीं है जितना कि एक नोड के तत्काल बच्चों के लिए जाँच करना।

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

      3(1)
    /     \
  2(1)     4(1)

और डुप्लिकेट "3" कुंजी डालने के बाद यह बन जाएगा:

      3(2)
    /     \
  2(1)     4(1)

यह कुछ अतिरिक्त बाइट्स और काउंटर ऑपरेशंस की कीमत पर लुकअप, रिमूवल और इंसर्शन ऑपरेशंस को सरल करता है।


मुझे बहुत आश्चर्य है कि इसका उपयोग उस पाठ्यपुस्तक में भी नहीं किया गया है जिसका मैं उपयोग कर रहा हूं। प्रोफेसर ने या तो इसका उल्लेख नहीं किया, न ही इस तथ्य से कि डुप्लिकेट कीज़ भी एक इश्यू smh हैं ...
Oloff Biermann

22

BST में, नोड के बाईं ओर नीचे उतरने वाले सभी मान नोड से कम (या बराबर, बाद में देखें) से कम होते हैं। इसी तरह, नोड के दाईं ओर नीचे आने वाले सभी मान नोड मान (ए) से अधिक (या बराबर ) हैं

कुछ BST डुप्लिकेट मानों की अनुमति देने का विकल्प चुन सकते हैं, इसलिए "ऊपर या नीचे" क्वालिफायर के बराबर है।

निम्नलिखित उदाहरण स्पष्ट कर सकते हैं:

            |
      +--- 14 ---+
      |          |
+--- 13    +--- 22 ---+
|          |          |
1         16    +--- 29 ---+
                |          |
               28         29

यह एक BST दिखाता है जो डुप्लिकेट की अनुमति देता है - आप देख सकते हैं कि एक मान खोजने के लिए, आप रूट नोड पर शुरू करते हैं और बाईं या दाईं उप-सीमा के नीचे जाते हैं, यह निर्भर करता है कि आपका खोज मान नोड मान से कम या अधिक है या नहीं।

यह कुछ इस तरह से किया जा सकता है:

def hasVal (node, srchval):
    if node == NULL:
         return false
    if node.val == srchval:
        return true
    if node.val > srchval:
        return hasVal (node.left, srchval)
    return hasVal (node.right, srchval)

और इसके साथ कॉल करना:

foundIt = hasVal (rootNode, valToLookFor)

डुप्लिकेट एक छोटी सी जटिलता को जोड़ते हैं क्योंकि आपको एक ही मूल्य के अन्य नोड्स के लिए अपना मूल्य मिल जाने के बाद खोज जारी रखने की आवश्यकता हो सकती है।


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


डुप्लिकेट मामले के लिए, क्या आप जांच सकते हैं कि क्या सही बच्चा नोड में वर्तमान नोड के समान है। == srchval: खंड, और फिर यदि सही है?
bnil

9

"इंट्रोडक्शन टू अल्गोरिदम" पुस्तक में, कॉर्मेन, लिसेर्सन, रिवेस्ट और स्टीन द्वारा तीसरा संस्करण, एक बाइनरी सर्च ट्री (BST) को स्पष्ट रूप से डुप्लिकेट की अनुमति के रूप में परिभाषित किया गया है । यह आंकड़ा 12.1 और निम्नलिखित में देखा जा सकता है (पृष्ठ 287):

"एक द्विआधारी खोज वृक्ष में कुंजी हमेशा इस तरह से बाइनरी-खोज-वृक्ष संपत्ति को पूरा करने के रूप में में जमा हो जाती: Let x। एक द्विआधारी खोज वृक्ष में एक नोड हो तो yके बाईं सबट्री में एक नोड है x, तो y:key <= x:key। तो yहै के उप उपशीर्षक में एक नोड x, फिर y:key >= x:key। "

इसके अलावा, एक लाल-काले पेड़ को तब पृष्ठ 308 के रूप में परिभाषित किया गया है:

"एक लाल-काला पेड़ एक बाइनरी सर्च ट्री है जिसमें प्रति नोड एक अतिरिक्त बिट स्टोरेज है: इसका रंग"

इसलिए, इस पुस्तक में परिभाषित लाल-काले पेड़ डुप्लिकेट का समर्थन करते हैं।


4

कोई भी परिभाषा मान्य है। जब तक आप अपने कार्यान्वयन में सुसंगत हैं (हमेशा बराबर नोड्स को दाईं ओर रखें, हमेशा उन्हें बाईं ओर रखें, या कभी भी उन्हें अनुमति न दें) तो आप ठीक हैं। मुझे लगता है कि उन्हें अनुमति नहीं देना सबसे आम है, लेकिन यह अभी भी एक BST है अगर उन्हें अनुमति दी गई है और या तो बाएं या दाएं जगह है।


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

1
विकी से यह भी ध्यान दें कि सही सबट्री में "रूट से अधिक या बराबर" मान शामिल हैं। इसलिए विकी की परिभाषा स्व-विरोधाभासी है।
सोपबॉक्‍स

1
+1: विभिन्न लोग विभिन्न परिभाषाओं का उपयोग करते हैं। यदि आप एक नए BST को लागू करते हैं, तो आपको यह सुनिश्चित करने की आवश्यकता है कि आप उन मान्यताओं के बारे में स्पष्ट हैं जो आप डुप्लिकेट प्रविष्टियों के बारे में बना रहे हैं।
श्री फूज

1
डुप्लिकेट की अनुमति देते समय आम सहमति की तरह लगता है (बाएं <= जड़ <सही)। लेकिन यह कि कुछ लोग BST की परिभाषा दुपट्टे की अनुमति नहीं देते हैं। या हो सकता है कि कुछ लोग इसे अतिरिक्त जटिलता से बचने का तरीका सिखाएं।
टिम मेरिफिल्ड

1
गलत! यह EITHER छोड़ दिया गया है <= root <right या left <root <= right, or left> root> = right or left> = root> right
मिच गेहूं

3

एक लाल-काले पेड़ के कार्यान्वयन पर काम करना मुझे कई कुंजियों के साथ पेड़ को सत्यापित करने में समस्या हो रही थी जब तक मुझे एहसास नहीं हुआ कि लाल-काले सम्मिलित घुमाव के साथ, आपको बाधा को ढीला करना होगा

left <= root <= right

चूंकि डॉक्यूमेंट में से कोई भी मैं डुप्लिकेट कुंजियों के लिए अनुमति नहीं देख रहा था और मैं इसके लिए रोटेशन के तरीकों को फिर से लिखना नहीं चाहता था, मैंने सिर्फ नोड के भीतर कई मानों की अनुमति देने के लिए अपने नोड्स को संशोधित करने का फैसला किया था, और कोई डुप्लिकेट कुंजी नहीं। पेड़।


2

आपने जो तीन बातें कही हैं, वे सब सच हैं।

  • कुंजी अद्वितीय हैं
  • बाईं ओर की चाबियाँ इस से कम हैं
  • सही करने के लिए यह एक से अधिक चाबियाँ हैं

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


1

1.) बायाँ <= जड़ <दायें

2.) बायाँ <root <= right

3.) बायां <रूट <सही, ऐसा है कि कोई डुप्लिकेट कुंजी मौजूद नहीं है।

मुझे अपनी एल्गोरिथ्म की किताबों को खोदना और खोदना पड़ सकता है, लेकिन मेरे सिर के ऊपर (3) विहित रूप है।

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


क्या आप बता सकते हैं कि बाएं <= रूट <= सही क्यों नहीं आदर्श है?
हेलिन वांग

@Paxdiablo द्वारा स्वीकृत उत्तर पर एक नज़र डालें - आप देख सकते हैं कि डुप्लिकेट मान मौजूद हो सकता है >=आदर्श आपकी आवश्यकताओं पर निर्भर करता है, लेकिन यदि आपके पास बहुत अधिक डुप्लिकेट मान हैं, और आप डुप्लिकेट को संरचना में मौजूद होने की अनुमति देते हैं, तो आपका बीटी रैखिक हो सकता है - यानी ओ (एन)।
रॉबर्ट पॉलसन

1

डुप्लिकेट कुंजी • एक ही कुंजी के साथ एक से अधिक डेटा आइटम होने पर क्या होता है? - यह लाल-काले पेड़ों में एक मामूली समस्या प्रस्तुत करता है। - यह महत्वपूर्ण है कि एक ही कुंजी के साथ नोड्स को एक ही कुंजी के साथ अन्य नोड्स के दोनों किनारों पर वितरित किया जाता है। - अर्थात्, यदि 50, 50, 50, 50 के क्रम में चाबियाँ आती हैं, तो आप चाहते हैं कि दूसरा 50 पहले वाले के दाईं ओर जाए, और तीसरा 50 पहले वाले के बाईं ओर जाने के लिए। • अन्यथा, पेड़ असंतुलित हो जाता है। • यह सम्मिलन एल्गोरिथ्म में किसी प्रकार की यादृच्छिक प्रक्रिया द्वारा नियंत्रित किया जा सकता है। - हालांकि, खोज प्रक्रिया तब और अधिक जटिल हो जाती है यदि एक ही कुंजी वाली सभी चीजें मिलनी चाहिए। • यह एक ही कुंजी के साथ आइटम को रेखांकित करने के लिए सरल है। - इस चर्चा में हम मान लेंगे कि डुप्लिकेट की अनुमति नहीं है

वृक्ष के प्रत्येक नोड के लिए एक लिंक की गई सूची बना सकते हैं जिसमें डुप्लिकेट कुंजियाँ होती हैं और सूची में डेटा संग्रहीत करती हैं।


1

मैं सिर्फ कुछ और जानकारी जोड़ना चाहता हूं जो @Robert पॉलसन ने उत्तर दिया।

मान लेते हैं कि नोड में कुंजी और डेटा है। तो एक ही कुंजी वाले नोड में अलग-अलग डेटा हो सकते हैं।
(इसलिए खोज को एक ही कुंजी के साथ सभी नोड्स खोजने होंगे)

1) बाएं <= वक्र <दायां

2) बायां <करण <= दायां

3) बाएं <= वक्र <= दाएं

4) बायाँ <cur <दाएँ && वक्र में एक ही कुंजी के साथ सहोदर नोड होते हैं ।

5) बायाँ <cur <दायां, जैसे कि कोई डुप्लिकेट कुंजी मौजूद नहीं है।

1) और 2) ठीक काम करता है अगर पेड़ को तिरछेपन को रोकने के लिए रोटेशन से संबंधित कोई कार्य नहीं होता है ।
लेकिन यह फॉर्म AVL ट्री या रेड-ब्लैक ट्री के साथ काम नहीं करता है , क्योंकि रोटेशन प्रिंसिपल को तोड़ देगा। और यहां तक ​​कि अगर खोज () कुंजी के साथ नोड का पता लगाता है, तो इसे डुप्लिकेट कुंजी के साथ नोड्स के लिए पत्ती नोड को नीचे करना होगा। खोज के लिए समय जटिलता बनाना = थीटा (logN)

3) रोटेशन से संबंधित कार्यों के साथ BST के किसी भी रूप में अच्छी तरह से काम करेगा।
लेकिन खोज O (n) लेगा , BST का उपयोग करने के उद्देश्य को बर्बाद कर देगा।
कहो कि हमारे पास नीचे पेड़ है, 3) मूलधन के साथ।

         12
       /    \
     10     20
    /  \    /
   9   11  12 
      /      \
    10       12

यदि हम इस पेड़ पर खोज (12) करते हैं, तो भी हमें 12 जड़ें मिलीं, हमें डुप्लिकेट कुंजी की तलाश करने के लिए बाएं और दाएं बच्चे दोनों की खोज करनी चाहिए।
जैसा कि मैंने बताया है ओ (एन) समय लगता है।

4) मेरा निजी पसंदीदा है। मान लीजिए कि सिबलिंग का मतलब एक ही कुंजी के साथ नोड है।
हम पेड़ से ऊपर नीचे में बदल सकते हैं।

         12 - 12 - 12
       /    \
10 - 10     20
    /  \    /
   9   11  12

अब कोई भी खोज O (logN) लेगा, क्योंकि हमें डुप्लिकेट कुंजी के लिए बच्चों को नहीं निकालना है।
और यह प्रिंसिपल AVL या RB ट्री के साथ भी अच्छा काम करता है ।


0

संबंध बनाने वाले तत्व <= कुल आदेश है इसलिए संबंध को रिफ्लेक्सिव होना चाहिए लेकिन आमतौर पर एक द्विआधारी खोज वृक्ष (उर्फ बीएसटी) डुप्लिकेट के बिना एक पेड़ है।

अन्यथा अगर डुप्लिकेट हैं तो आपको दो बार या एक ही फ़ंक्शन को हटाने की आवश्यकता है!

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