Hogyan ellenőrizhetem, hogy a BST érvényes?

szavazat
6

Hogyan ellenőrizhetem, hogy a BST érvényes, lévén, hogy annak meghatározása, és egy általánosított változatát szeres 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)

Az ötlet az, hogy ellenőrizze, hogy a csomópont értéke nagyobb, akkor minden érték a bal részfa és kisebb, mint az összes érték a jobb részfa. Ezt kell Trueminden csomópont a fán. A funkció bstListegyszerűen kiírja a listát (rendelt) értékeket a BST.

Persze ilyesmit nem fog működni:

--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

mert például, alkalmazva a hajtogatási funkció a csomóponthoz 19végződik all (<19) (bstList True) && all (>19) (bstList True).

BST

A kérdést 12/02/2011 23:22
a forrás felhasználó
Más nyelveken...                            


4 válasz

szavazat
4

A probléma az lehet, hogy elveszíti az információt, mert a funkció csak boolean típusú vizsgálata során a bal és a jobb részfa. Tehát változtassa meg is visszatérhet a minimum és maximum értékei részfák. (Ez talán hatékonyabb is, hiszen nem kell a használt bslist, hogy ellenőrizze az összes elemet már)

És egy wrapper függvény figyelmen kívül hagyja ezeket a „kisegítő” értékek Miután elkészült, természetesen.

Válaszolt 12/02/2011 23:38
a forrás felhasználó

szavazat
4

(Kérem, ne tegye typeclass korlátokat a datatípusát.)

A BST érvényes IFF in-order bejárás monoton nő.

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

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

isBST = ordered . flatten
Válaszolt 13/02/2011 05:53
a forrás felhasználó

szavazat
0

Ha nem ragaszkodunk a fold megteheti, mint ez:

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
Válaszolt 13/02/2011 07:45
a forrás felhasználó

szavazat
2

Egy szép módja kódoló ez támaszkodik a bejárás által Data.Foldable.

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

Mi lehet levezetni egy példánya automatikusan hosszabbító, de meg kell rendezni a területeken a Node kivitelező, hogy adjon nekünk egy in-sorrendben bejárás.

Ha már itt tartunk, mi megszünteti a korlátozásokat az adatok típusát is. Ezek valóban nem nyújt előnyt, és már eltávolították a nyelvet, mint a Haskell 2011. (Ha szeretné, hogy az ilyen korlátozások akkor tedd esetekben az osztályok, nem az adatok típusát.)

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

Először határozza meg, hogy mit jelent egy listát szigorúan kell válogatni.

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.

Akkor tudjuk használni a toListmódszernek, Data.Foldableés a fenti segítő.

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

Azt is alkalmazzák ezt a közvetlenebb, ahogy kérted. Mivel mi eltávolítjuk a zavaró korlátokat az adatok típusát, akkor egyszerűsíteni a meghatározása a fold.

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)

Most szükségünk van egy adattípust modellezésére az eredmény a mi catamorphism, ami az, hogy vagy nincs csomópontok ( Z), illetve számos, szigorúan növekvő csomópontok ( T) vagy sikertelen ( X)

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

És mi lehet majd végre isBSTközvetlenül

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

Ez egy kicsit unalmas, ezért talán jobb lenne, elbontása, ahogy mi össze az átmeneti állapotok egy kicsit:

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

Személy szerint én talán csak használja a Összecsukható példány.

Válaszolt 13/02/2011 16:31
a forrás felhasználó

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