Ось спосіб це зробити, не згладжуючи дерево.
З визначення, тут,
data BinaryTree a = Null | Node (BinaryTree a) a (BinaryTree a)
deriving Show
видно, що проходження дерева ліворуч праворуч, ігнорування Node
та круглі дужки дає чергування послідовностей Null
s і a
s. Тобто між кожними двома значеннями є а 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
Обчислення фактичних крайніх значень у кожному піддереві, виведення їх назовні, дає вам більше інформації, ніж вам потрібно, і непомітно у крайніх випадках, коли ліве або праве піддерево порожнє. Дотримання та перевірка вимог , штовхаючи їх всередину, є більш рівномірним.
flattenTree
спочатку. Ви можете повернутисяFalse
достроково, якщо вузол порушує пошукову властивість, не маючи необхідності переходити все піддерево, вкорінене на цьому вузлі.