Cum pot verifica dacă un BST este valabil?

voturi
6

Cum pot verifica dacă un BST este una valabilă, având în vedere definiția și folosind o versiune generalizată de ori mai mare pentru BST sale?

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)

Ideea este de a verifica dacă o valoare nod este mai mare , atunci toate valorile din stânga-subarborele și mai mici decât toate valorile din dreapta sa-subramificație. Acest lucru trebuie să fie Truepentru toate nodurile din arbore. O funcție bstListpur și simplu de ieșire lista de valori (ordonate) în BST.

Desigur, ceva de genul acesta nu va funcționa:

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

deoarece, de exemplu, aplicarea funcției ori la nodul 19sfarseste all (<19) (bstList True) && all (>19) (bstList True).

un

Întrebat 12/02/2011 la 23:22
sursa de către utilizator
În alte limbi...                            


4 răspunsuri

voturi
4

Problema ta pare să fie că vă pierdeți informații , deoarece funcția returnează doar un boolean când examinează subramificații stânga și dreapta. Deci , schimba pentru a reveni , de asemenea , valorile minime și maxime ale subramificații. (Acest lucru este , probabil , mai eficient, de asemenea, din moment ce nu trebuie să folosite bslistpentru a verifica toate elementele de mai)

Și să facă o funcție de înveliș pentru a ignora aceste valori „auxiliare“, după ce ați terminat, desigur.

Publicat 12/02/2011 la 23:38
sursa de către utilizator

voturi
4

(Vă rugăm să nu pun constrângeri typeclass pe datatipul.)

Un BST este valabil IFF o în ordine parcurgeri este în creștere monoton.

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

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

isBST = ordered . flatten
Publicat 13/02/2011 la 05:53
sursa de către utilizator

voturi
0

Dacă nu insista pe utilizarea unui pliu poti face ca acest lucru:

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
Publicat 13/02/2011 la 07:45
sursa de către utilizator

voturi
2

Un mod frumos de codificare acest lucru este să se sprijine pe traversal furnizate de Data.Foldable.

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

Putem obține o instanță a acestuia, folosind în mod automat o extensie, dar avem nevoie pentru a rearanja câmpurile constructorului Node pentru a ne oferi un parcurgeri în ordine.

În timp ce suntem la ea, ar trebui să elimine constrângerile privind tipul de date în sine. Ele oferă de fapt nici un beneficiu, și a fost eliminată din limba ca Haskell 2011. (Când doriți să utilizați astfel de constrângeri ar trebui să le pună pe cazuri de clase, nu pe tipul de date.)

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

Mai întâi definim ce înseamnă o listă care urmează să fie strict sortate.

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.

Apoi , putem folosi toListmetoda furnizată de Data.Foldableși Helper de mai sus.

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

Putem pune în aplicare, de asemenea, acest lucru mai direct, cum ai cerut. Din moment ce am eliminat constrângerile false privind tipul de date, putem simplifica definiția 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)

Acum avem nevoie de un tip de date pentru a modela rezultatul catamorphism noastre, care este că fie nu avem noduri ( Z), sau o serie de noduri strict crescătoare ( T) sau au eșuat ( X)

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

Și atunci putem pune în aplicare în mod isBSTdirect

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

Acesta este un pic plictisitoare, asa ca, probabil ar fi mai bine să se descompună modul în care compun statele interimare un pic:

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

Personal, probabil că aș folosi doar instanță pliabil.

Publicat 13/02/2011 la 16:31
sursa de către utilizator

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