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)
Lo que quiero hacer es escribir una función para determinar si el árbol dado es un árbol de búsqueda binario, mi método es agrupar todos los valores en una lista e importarlos Data.List
y luego ordenar la lista para encontrar si son iguales, pero Es un poco complicado. ¿Podemos hacer esto sin importar otro módulo?
haskell
tree
binary-tree
binary-search-tree
predicate
Jayyyyyy
fuente
fuente
flattenTree
primero. Puede regresarFalse
temprano si un nodo viola la propiedad de búsqueda sin tener que atravesar todo el subárbol enraizado en ese nodo.sort
, no conflattenTree
, que es lo suficientemente flojo.Respuestas:
Aquí hay una manera de hacerlo sin aplanar el árbol.
De la definición, aquí,
Uno puede ver que atravesar el árbol de izquierda a derecha, ignorando
Node
y entre paréntesis, le da una secuencia alterna deNull
sya
s. Es decir, entre cada dos valores, hay unNull
.Mi plan es verificar que cada subárbol satisfaga los requisitos adecuados : podemos refinar los requisitos en cada uno
Node
, recordando qué valores estamos entre ellos, y luego probarlos en cada unoNull
. Como hay unNull
par de valores entre cada orden, habremos probado que todos los pares en orden (de izquierda a derecha) no disminuyen.¿Qué es un requisito? Es un límite inferior y superior suelto en los valores del árbol. Para expresar los requisitos, incluidos los que se encuentran en los extremos más a la izquierda y a la derecha, podemos extender cualquier pedido con
Bot
tom yTop
elementos, de la siguiente manera:Ahora, verifiquemos que un árbol determinado cumpla con los requisitos de estar en orden y entre límites dados.
Un árbol de búsqueda binaria es un árbol que está en orden y entre
Bot
yTop
.El cálculo de los actuales valores extremales en cada sub-árbol, burbujeando ellos hacia el exterior, le da más información que usted necesita, y es más incómoda en los casos extremos donde un subárbol izquierdo o derecho está vacío. Mantener y verificar los requisitos , empujándolos hacia adentro, es bastante más uniforme.
fuente
Aquí hay una pista: hacer una función auxiliar
donde
BSTResult a
se define comoDebería poder proceder de manera recursiva, explotando los resultados en subárboles para impulsar el cálculo, en particular el mínimo y el máximo.
Por ejemplo, si tiene
tree = Node left 20 right
, conisBSTree' left = NonEmptyBST 1 14
yisBSTree' right = NonEmptyBST 21 45
, entoncesisBSTree' tree
debería serNonEmptyBST 1 45
.En el mismo caso, excepto
tree = Node left 24 right
, deberíamos tenerisBSTree' tree = NotBST
.Convertir el resultado a
Bool
es trivial.fuente
BSTResult a
y doblar en él. :) (o incluso si no es un monoide legal ...)Sí , no necesita ordenar la lista. Puede verificar si cada elemento es menor o igual que el siguiente elemento. Esto es más eficiente ya que podemos hacer esto en O (n) , mientras que la evaluación de la lista ordenada requiere completamente O (n log n) .
Así podemos verificar esto con:
Entonces podemos verificar si el árbol binario es un árbol de búsqueda binario con:
Creo que se puede afirmar que
Null
es un árbol de búsqueda binario, ya que es un árbol vacío. Esto significa que para cada nodo (no hay nodos) los elementos en el subárbol izquierdo son menores o iguales al valor en el nodo, y los elementos en el subárbol derecho son todos mayores o iguales al valor en el nodo .fuente
Podemos proceder de izquierda a derecha sobre el árbol de esta manera:
Inspirado por John McCarthy's
gopher
.La lista desplegable explícita se puede eliminar con el paso de continuación,
Mantener solo uno, el elemento más grande hasta ahora , es suficiente.
fuente