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)
Chcę napisać funkcję określającą, czy dane drzewo jest drzewem wyszukiwania binarnego, moja metoda polega na zgrupowaniu wszystkich wartości na liście i zaimportowaniu, Data.List
a następnie posortowaniu listy, aby sprawdzić, czy są one równe, ale to jest trochę skomplikowane. Czy możemy to zrobić bez importowania innego modułu?
haskell
tree
binary-tree
binary-search-tree
predicate
Jayyyyyy
źródło
źródło
flattenTree
pierwszego. Możesz wrócićFalse
wcześniej, jeśli węzeł narusza właściwość wyszukiwania bez konieczności przechodzenia przez całe poddrzewo zrootowane w tym węźle.sort
, a nie zflattenTree
, który jest wystarczająco leniwy.Odpowiedzi:
Oto sposób na zrobienie tego bez spłaszczania drzewa.
Z definicji tutaj
widać, że przemierzanie drzewa od lewej do prawej, ignorowanie
Node
i nawiasy, daje naprzemienną sekwencjęNull
s ia
s. Oznacza to, że między każdymi dwiema wartościami jestNull
.Moim planem jest sprawdzenie, czy każde poddrzewo spełnia odpowiednie wymagania : możemy uszczegółowić wymagania dla każdego z nich
Node
, pamiętając, które wartości są pomiędzy, a następnie przetestować je dla każdego z nichNull
. Ponieważ istniejeNull
para wartości między kolejnymi wartościami, sprawdzimy, czy wszystkie pary w kolejności (od lewej do prawej) nie maleją.Co jest wymagane? Jest to luźna dolna i górna granica wartości w drzewie. Aby wyrazić wymagania, w tym te na skraju lewej i skrajnej prawej strony, możemy rozszerzyć dowolne zamówienie o
Bot
tom iTop
elementy w następujący sposób:Sprawdźmy teraz, czy dane drzewo spełnia wymagania bycia zarówno w porządku, jak i między podanymi granicami.
Drzewo wyszukiwania binarnego to drzewo, które jest w porządku oraz między
Bot
iTop
.Obliczanie rzeczywistych wartości ekstremalnych w każdym poddrzewie, propagowanie ich na zewnątrz, daje więcej informacji, niż potrzebujesz, i jest kłopotliwe w skrajnych przypadkach, w których lewe lub prawe poddrzewo jest puste. Utrzymywanie i sprawdzanie wymagań , popychanie ich do wewnątrz, jest raczej bardziej jednolite.
źródło
Oto podpowiedź: wykonaj funkcję pomocniczą
gdzie
BSTResult a
jest zdefiniowany jakoPowinieneś być w stanie kontynuować rekurencyjnie, wykorzystując wyniki w poddrzewach do kierowania obliczeniami, w szczególności minimum i maksimum.
Na przykład, jeśli masz
tree = Node left 20 right
, przy pomocyisBSTree' left = NonEmptyBST 1 14
iisBSTree' right = NonEmptyBST 21 45
, toisBSTree' tree
powinno byćNonEmptyBST 1 45
.W tym samym przypadku, z wyjątkiem
tree = Node left 24 right
, powinniśmy zamiast tegoisBSTree' tree = NotBST
.Konwersja wyniku
Bool
jest wtedy trywialna.źródło
BSTResult a
i złóż je. :) (a nawet jeśli nie jest to legalny Monoid ....)Tak , nie musisz sortować listy. Możesz sprawdzić, czy każdy element jest mniejszy lub równy następnemu elementowi. Jest to bardziej wydajne, ponieważ możemy to zrobić w O (n) , podczas gdy ocena posortowanej listy całkowicie zajmuje O (n log n) .
Możemy to sprawdzić za pomocą:
Możemy więc sprawdzić, czy drzewo binarne jest drzewem wyszukiwania binarnego za pomocą:
Myślę, że można twierdzić, że
Null
samo jest drzewem wyszukiwania binarnego, ponieważ jest to puste drzewo. Oznacza to zatem, że dla każdego węzła (nie ma węzłów) elementy w lewym poddrzewie są mniejsze lub równe wartości w węźle, a elementy w prawym poddrzewie są większe lub równe wartości w węźle .źródło
Możemy przejść od lewej do prawej nad drzewem w następujący sposób:
Inspirowany przez Johna McCarthy'ego
gopher
.Wyraźną listę rozwijaną można wyeliminować poprzez przekazywanie kontynuacji,
Wystarczy tylko jeden, jak dotąd największy element.
źródło