खोजें कि क्या कोई पेड़ हास्केल में एक द्विआधारी खोज पेड़ है


10
  type BSTree a = BinaryTree a

  data BinaryTree a = Null | Node (BinaryTree a) a (BinaryTree a)
                      deriving Show

  flattenTree :: BinaryTree a -> [a]
  flattenTree  tree = case tree of
      Null -> []
      Node left val right -> (flattenTree left) ++ [val] ++ (flattenTree right)

  isBSTree :: (Ord a) => BinaryTree a -> Bool
  isBSTree btree = case btree of
      Null -> False
      tree -> (flattenTree tree) == sort (flattenTree tree)

मैं क्या करना चाहता हूं यह निर्धारित करने के लिए एक फ़ंक्शन लिखना है कि क्या दिया गया पेड़ एक द्विआधारी खोज पेड़ है, मेरी विधि सभी मूल्यों को एक सूची और आयात में समूहित करना है Data.Listऔर फिर सूची को खोजने के लिए क्रमबद्ध करें कि क्या वे समान हैं, लेकिन यह थोड़ा जटिल है। क्या हम अन्य मॉड्यूल आयात किए बिना ऐसा कर सकते हैं?


मैं flattenTreeपहले परिभाषित नहीं करेगा । Falseयदि कोई नोड उस नोड पर रूट किए गए पूरे सबट्री को पार किए बिना खोज प्रॉपर्टी का उल्लंघन करता है, तो आप जल्दी लौट सकते हैं ।
शेपनर

@ सभी को समस्या है sort, साथ नहीं है flattenTree, जो पर्याप्त आलसी है।
विल नेस

हाँ, यह कुछ अन्य उत्तरों को देखने के बाद मुझे हुआ।
चेप्टर

जवाबों:


13

यहां पेड़ को समतल किए बिना इसे करने का एक तरीका है।

परिभाषा से, यहाँ,

data BinaryTree a = Null | Node (BinaryTree a) a (BinaryTree a)
     deriving Show

एक देख सकते हैं कि पेड़ traversing बाएं से दाएं, अनदेखी Nodeऔर कोष्ठक, आप में से एक वैकल्पिक अनुक्रम देता Nullहै और aरों। है यही कारण है, हर दो मानों के बीच, वहाँ एक है Null

मेरी योजना यह जांचना है कि प्रत्येक उपप्रकार उपयुक्त आवश्यकताओं को संतुष्ट करता है : हम प्रत्येक पर आवश्यकताओं को परिष्कृत कर सकते हैं Node, यह याद रखते हुए कि हम किन मूल्यों के बीच हैं, फिर प्रत्येक पर उनका परीक्षण करें Null। जैसा कि Nullमूल्यों की जोड़ी में प्रत्येक के बीच होता है, हमने परीक्षण किया होगा कि सभी क्रम में (बाएं से दाएं) जोड़े गैर-घटते हैं।

एक आवश्यकता क्या है? यह पेड़ में मूल्यों पर एक ढीला निचला और ऊपरी बाध्य है। आवश्यकताओं को व्यक्त करने के लिए, सबसे बाईं और दाईं ओर के सिरे सहित, हम Botटॉम और Topतत्वों के साथ किसी भी क्रम का विस्तार कर सकते हैं , निम्नानुसार हैं:

data TopBot a = Bot | Val a | Top deriving (Show, Eq, Ord)

अब हम जाँचते हैं कि एक दिया गया पेड़ क्रम में और दिए गए सीमा के बीच दोनों की आवश्यकताओं को संतुष्ट करता है।

ordBetween :: Ord a => TopBot a -> TopBot a -> BinaryTree a -> Bool
  -- tighten the demanded bounds, left and right of any Node
ordBetween lo hi (Node l x r) = ordBetween lo (Val x) l && ordBetween (Val x) hi r
  -- check that the demanded bounds are in order when we reach Null
ordBetween lo hi Null         = lo <= hi

एक द्विआधारी खोज पेड़ एक पेड़ है जो क्रम में और बीच में Botऔर है Top

isBSTree :: Ord a => BinaryTree a -> Bool
isBSTree = ordBetween Bot Top

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


6

यहाँ एक संकेत है: एक सहायक कार्य करें

isBSTree' :: (Ord a) => BinaryTree a -> BSTResult a

जहां BSTResult aके रूप में परिभाषित किया गया है

data BSTResult a
   = NotBST             -- not a BST
   | EmptyBST           -- empty tree (hence a BST)
   | NonEmptyBST a a    -- nonempty BST with provided minimum and maximum

आपको गणना करने के लिए उपप्रकार पर परिणामों का दोहन करते हुए, पुनरावर्ती रूप से आगे बढ़ने में सक्षम होना चाहिए, विशेष रूप से न्यूनतम और अधिकतम।

उदाहरण के लिए, यदि आपके पास tree = Node left 20 right, isBSTree' left = NonEmptyBST 1 14और isBSTree' right = NonEmptyBST 21 45, तो isBSTree' treeहोना चाहिए NonEmptyBST 1 45

उसी मामले को छोड़कर tree = Node left 24 right, हमें इसके बजाय होना चाहिए isBSTree' tree = NotBST

Boolतब परिणाम को परिवर्तित करना तुच्छ है।


1
या इसके लिए स्पष्ट मोनॉइड को परिभाषित करें BSTResult aऔर उसमें गुना करें। :) (या यहां तक ​​कि अगर यह एक वैध मोनॉइड नहीं है ....)
विल नेस

(लेकिन यह वैध है, वैसे भी, मुझे लगता है)
विल नेस

3

हां , आपको सूची को क्रमबद्ध करने की आवश्यकता नहीं है। आप जांच सकते हैं कि हर तत्व अगले तत्व से कम या उसके बराबर है या नहीं। यह अधिक कुशल है क्योंकि हम इसे O (n) में कर सकते हैं , जबकि क्रमबद्ध सूची का मूल्यांकन पूरी तरह से O (n log n) लेता है ।

हम इस प्रकार से इसकी जाँच कर सकते हैं:

ordered :: Ord a => [a] -> Bool
ordered [] = True
ordered xa@(_:xs) = and (zipWith (<=) xa xs)

तो हम जांच सकते हैं कि क्या बाइनरी ट्री एक बाइनरी सर्च ट्री है:

isBSTree :: Ord a => BinaryTree a -> Bool
isBSTree = ordered . flattenTree

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


1

हम इस तरह से पेड़ पर बाएं से दाएं आगे बढ़ सकते हैं:

isBSTtreeG :: Ord a => BinaryTree a -> Bool
isBSTtreeG t = gopher Nothing [Right t]
    where
    gopher  _   []                        =  True
    gopher  x   (Right Null:ts)           =  gopher x ts
    gopher  x   (Right (Node lt v rt):ts) =  gopher x (Right lt:Left v:Right rt:ts)
    gopher Nothing   (Left v:ts)          =  gopher (Just v) ts
    gopher (Just y)  (Left v:ts)          =  y <= v && gopher (Just v) ts

जॉन मैकार्थीgopher से प्रेरित है ।

स्पष्ट पुश-डाउन सूची को निरंतरता-गुजरने के साथ समाप्त किया जा सकता है,

isBSTtreeC :: Ord a => BinaryTree a -> Bool
isBSTtreeC t = gopher Nothing t (const True)
    where
    gopher  x   Null           g  =  g x 
    gopher  x   (Node lt v rt) g  =  gopher x lt (\case
                                       Nothing -> gopher (Just v) rt g
                                       Just y  -> y <= v && gopher (Just v) rt g)

केवल एक को बनाए रखना, सबसे बड़ा-अब तक का तत्व, पर्याप्त है।

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