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)
O que eu quero fazer é escrever uma função para determinar se a árvore especificada é uma árvore de pesquisa binária, meu método é agrupar todos os valores em uma lista e importar Data.List
e, em seguida, classificar a lista para descobrir se são iguais, mas é um pouco complicado. Podemos fazer isso sem importar outro módulo?
haskell
tree
binary-tree
binary-search-tree
predicate
Jayyyyyy
fonte
fonte
flattenTree
primeiro. Você pode retornarFalse
cedo se um nó violar a propriedade de pesquisa sem precisar percorrer toda a subárvore enraizada nesse nó.sort
, não comflattenTree
, o que é preguiçoso o suficiente.Respostas:
Aqui está uma maneira de fazer isso sem achatar a árvore.
A partir da definição, aqui,
pode-se ver que percorrer a árvore da esquerda para a direita, ignorando
Node
e parênteses, fornece uma sequência alternada deNull
s ea
s. Ou seja, entre cada dois valores, existe umNull
.Meu plano é verificar se cada subárvore atende aos requisitos adequados : podemos refinar os requisitos em cada um
Node
, lembrando quais valores estamos entre eles e testá- los em cada umNull
. Como existe umNull
par de valores entre todos os em ordem, teremos testado que todos os pares em ordem (da esquerda para a direita) não diminuem.O que é um requisito? É um limite inferior e superior solto nos valores da árvore. Para expressar requisitos, incluindo aqueles nas extremidades mais à esquerda e à direita, podemos estender qualquer pedido com
Bot
tom eTop
elementos, da seguinte maneira:Agora vamos verificar se uma determinada árvore atende aos requisitos de estar em ordem e entre limites determinados.
Uma árvore de pesquisa binária é uma árvore que está em ordem e entre
Bot
eTop
.A computação dos valores extremais reais em cada subárvore, borbulhando para fora, fornece mais informações do que você precisa e é minuciosa nos casos extremos em que uma subárvore esquerda ou direita está vazia. Manter e verificar os requisitos , empurrando-os para dentro, é bastante mais uniforme.
fonte
Aqui está uma dica: crie uma função auxiliar
onde
BSTResult a
é definido comoVocê deve poder recursivamente, explorando resultados em subárvores para conduzir o cálculo, em particular o mínimo e o máximo.
Por exemplo, se você tiver
tree = Node left 20 right
, comisBSTree' left = NonEmptyBST 1 14
eisBSTree' right = NonEmptyBST 21 45
, entãoisBSTree' tree
deve serNonEmptyBST 1 45
.No mesmo caso, exceto
tree = Node left 24 right
, deveríamos terisBSTree' tree = NotBST
.Converter o resultado para
Bool
é então trivial.fonte
BSTResult a
e dobre nele. :) (ou mesmo se não é um Monoid legal ....)Sim , você não precisa classificar a lista. Você pode verificar se cada elemento é menor ou igual ao próximo elemento. Isso é mais eficiente, pois podemos fazer isso em O (n) , enquanto avaliar a lista classificada leva completamente O (n log n) .
Assim, podemos verificar isso com:
Portanto, podemos verificar se a árvore binária é uma árvore de pesquisa binária com:
Penso que se pode afirmar que
Null
é uma árvore de pesquisa binária, uma vez que é uma árvore vazia. Isso significa que, para cada nó (não há nós), os elementos na subárvore esquerda são menores ou iguais ao valor no nó, e os elementos na subárvore direita são todos maiores ou iguais ao valor no nó .fonte
Podemos prosseguir da esquerda para a direita sobre a árvore desta maneira:
Inspirado por John McCarthy
gopher
.A lista push-down explícita pode ser eliminada com a passagem de continuação,
Manter apenas um, o maior elemento até agora , é suficiente.
fonte