मैं कैसे जांच कर सकते हैं एक BST मान्य है?

वोट
6

मैं कैसे जांच कर सकते हैं एक BST एक वैध एक, इसकी परिभाषा और BST के लिए गुना की एक सामान्यीकृत संस्करण का उपयोग कर दिया है?

data(Ord a, Show a, Read  a) => BST a = Void | Node {
    val :: a,
    left, right :: BST a
} deriving (Eq,  Ord,  Read, Show)


fold :: (Read a, Show a, Ord a) => (a -> b -> b ->  b) -> b -> BST a -> b
fold _ z Void         = z
fold f z (Node x l r) = f x (fold f z l) (fold f z r)

विचार यह देखना होगा कि एक नोड मूल्य बाएं सबट्री में अधिक से अधिक सभी मूल्यों तो और इसकी सही-सबट्री में सभी मान से छोटा होता है है। यह होना चाहिए Trueपेड़ में सभी नोड्स के लिए। एक समारोह bstListबस (आदेश दिया) BST में मानों की सूची उत्पादन।

बेशक कुछ इस तरह काम नहीं करेगा:

--isBST :: (Read a, Show a, Ord a) => BST a -> Bool
isBST t = fold (\x l r -> all (<x) (bstList l) && all (>x) (bstList r)) (True) t

क्योंकि, उदाहरण के लिए, नोड के लिए गुना समारोह को लागू करने के 19समाप्त होता है all (<19) (bstList True) && all (>19) (bstList True)

एक

12/02/2011 को 23:22
का स्रोत उपयोगकर्ता
अन्य भाषाओं में...                            


4 जवाब

वोट
4

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

और एक आवरण समारोह इन "सहायक" मूल्यों की अनदेखी करने के बाद आप निश्चित रूप से, किया जाता है बनाते हैं।

12/02/2011 को 23:38
का स्रोत उपयोगकर्ता

वोट
4

(कृपया पर typeclass की कमी न रखें dataप्रकार।)

एक BST iff एक में आदेश ट्रावर्सल होगा- बढ़ती जा रही है मान्य है।

flatten tree = fold (\a l r -> l . (a:) . r) id tree []

ordered list@(_:rest) = and $ zipWith (<) list rest
ordered _ = True

isBST = ordered . flatten
13/02/2011 को 05:53
का स्रोत उपयोगकर्ता

वोट
0

यदि आप एक गुना के प्रयोग पर जोर देते हैं नहीं है, तो आप इस तरह यह कर सकते हैं:

ord Void = True
ord (Node v l r) = every (< v) l && every (> v) r && ord l && ord r where
    every p Void = True
    every p (Node v l r) = p v && every p l && every p r
13/02/2011 को 07:45
का स्रोत उपयोगकर्ता

वोट
2

इस एन्कोडिंग का एक अच्छा तरीका Data.Foldable द्वारा प्रदान की ट्रेवर्सल पर दुबला करने के लिए है।

{-# LANGUAGE DeriveFunctor, DeriveFoldable #-}
import Data.Foldable
import Data.Monoid

हम इसे का एक उदाहरण स्वचालित रूप से एक एक्सटेंशन का उपयोग प्राप्त कर सकते हैं, लेकिन हम नोड निर्माता के क्षेत्र को पुन: व्यवस्थित करने के लिए हमें एक में आदेश ट्रावर्सल प्रदान करने के लिए की जरूरत है।

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

data BST a 
  = Void
  | Node
    { left :: BST a
    , val :: a
    , right :: BST a 
    } deriving (Eq, Ord, Read, Show, Foldable)

पहले हम परिभाषित इसका क्या मतलब एक के लिए सूची सख्ती से क्रमबद्ध करना।

sorted :: Ord a => [a] -> Bool
sorted [] = True
sorted [x] = True
sorted (x:xs) = x < head xs && sorted xs 
-- head is safe because of the preceeding match.

फिर हम उपयोग कर सकते हैं toListविधि द्वारा प्रदान की Data.Foldableऔर इसके बाद के संस्करण सहायक।

isBST :: Ord a => BST a -> Bool
isBST = sorted . toList

हम भी इस अधिक सीधे लागू कर सकते हैं, जैसे आप से पूछा। जब से हम डेटा प्रकार पर नकली बाधाओं को हटा दिया है, हम अपने गुना की परिभाषा को आसान बनाने में कर सकते हैं।

cata :: (b -> a -> b -> b) -> b -> BST a -> b
cata _ z Void         = z
cata f z (Node l x r) = f (cata f z l) x (cata f z r)

अब हम हमारी catamorphism है, जो यह है कि हम या तो कोई नोड्स (राशि का परिणाम मॉडल करने के लिए डेटा प्रकार की जरूरत है Z), या सख्ती से बढ़ रही है नोड्स की एक सीमा ( T) या विफल रहे हैं ( X)

data T a = Z | T a a | X deriving Eq

और हम तो लागू कर सकते हैं isBSTसीधे

isBST' :: Ord a => BST a -> Bool
isBST' b = cata phi Z b /= X where
  phi X _ _ = X
  phi _ _ X = X
  phi Z a Z = T a a
  phi Z a (T b c) = if a < b then T a c else X
  phi (T a b) c Z = if b < c then T a c else X
  phi (T a b) c (T d e) = if b < c && c < d then T a e else X

इसमें कुछ समय कठिन है, इसलिए शायद यह बेहतर होगा जिस तरह से हम अंतरिम राज्यों थोड़ा रचना विघटित करने के लिए:

cons :: Ord a => a -> T a -> T a
cons _ X = X
cons a Z = T a a
cons a (T b c) = if a < b then T a c else X

instance Ord a => Monoid (T a) where
  mempty = Z
  Z `mappend` a = a
  a `mappend` Z = a
  X `mappend` _ = X
  _ `mappend` X = X
  T a b `mappend` T c d = if b < c then T a d else X

isBST'' :: Ord a => BST a -> Bool
isBST'' b = cata phi Z b /= X where
  phi l a r = l `mappend` cons a r

व्यक्तिगत रूप से, मैं शायद सिर्फ Foldable उदाहरण का उपयोग करेंगे।

13/02/2011 को 16:31
का स्रोत उपयोगकर्ता

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more