I am new to Haskell and I am trying to build a tree which holds integers and every element in the left subtree is <= node value.
This is the code that I have written so far but I don't know how to do the recursion inside. I would appreciate it if you could give me some guidance.
data Tree = Leaf | Node Int Tree Tree
deriving (Eq, Show, Read, Ord)
insert :: Int -> Tree -> Tree
insert x (Tree n i t1 t2) =
From what I understand is that I have to check each node of tree and see if there is an int to it and then recursively search the subtrees.
Please help
thanks
EDIT:
I managed to do something but it seems that the new nodes fail to be created or I am checking it wrong, this is the new code:
data Tree = Leaf | Node Int Tree Tree
deriving (Eq, Show, Read, Ord)
insert :: Int -> Tree -> Tree
insert x Leaf = Node x Leaf Leaf
insert x (Node i t1 t2)
| x <= i = insert x t1
| otherwise = insert x t2
To check it I write:
let tree = insert 5 (insert 10 ( insert 11 ( insert 12 (insert 15 tree))))
But when I write in the ghci:
tree
I get:
Node 5 Leaf Leaf
When you are inserting into a node, you are returning what would be inserted into one side of the Node, not a new Node with the data inserted into one side of it. Only at the Leaf level are you making a new node.
insert :: Int -> Tree -> Tree
insert x Leaf = Node x Leaf Leaf
insert x (Node i t1 t2)
| x <= i = Node i (insert x t1) t2
| otherwise = Node i t1 (insert x t2)
The problem with your recursive case for Node is that although you call insert to make a new sub tree on either the left or the right, you don't rebuild the parent tree afterwards, you just return the new sub tree.
For example the first case should be Node i (insert x t1) t2, and similarly for the second case.
Related
I am starting to learn Haskell and therefore I tried to implement a Binary Search Tree. My current code looks like this:
data SearchTree = Empty | Node Int SearchTree SearchTree
deriving Show
insert :: SearchTree -> Int -> SearchTree
insert Empty x = (Node x Empty Empty)
insert (Node n tl tr) x = if (x > n)
then insert tr x
else insert tl x
But somehow the second part of the insert function is not working correctly. If I try these lines of code:
insert (Node 2 Empty Empty) 4
the result is Node 4 Empty Empty instead of a result like: Node 2 Empty (Node 4 Empty Empty) that I expected.
Can someone tell me, what I did wrong?
Thanks :)
When you recurse, you lose the information on the outer node. You have to re-wrap the result in a Node:
data SearchTree = Empty | Node Int SearchTree SearchTree
deriving Show
insert :: SearchTree -> Int -> SearchTree
insert Empty x = (Node x Empty Empty)
insert (Node n tl tr) x = if (x > n)
-- note the Node n tl (new_branch)
then Node n tl (insert tr x)
else Node n (insert tl x) tr
Define, for a binary tree type Tree, a function which returns the number of nodes. I came up with this function but it does not run.
Error: Not in scope: data constructor'Node'
numberOfNodes :: Tree -> Int
numberOfNodes Null = 0
numberOfNodes (Node _ st1 st2) = 1 + max (st1)(st2)
The first issue is that you appear to be missing a definition for what a Tree is.
Generally we say it's either a Node with a value plus two subtrees, or it's empty.
Next, our recursive definition for the number of nodes in a (non-empty) tree should be:
number of nodes in left subtree + number of nodes in right subtree + 1
Here is a full definition:
data Tree a = Empty | Node a (Tree a) (Tree a) deriving (Show)
numberOfNodes :: Tree x -> Int
numberOfNodes Empty = 0
numberOfNodes (Node _ st1 st2) = 1 + numberOfNodes(st1) + numberOfNodes(st2)
(Note that we implement the Show typeclass so that we can print the tree)
If we define a binary tree with 3 nodes, see how it works:
myTree :: Tree Int
myTree =
Node 0
(Node 1 Empty Empty)
(Node 2 Empty Empty)
> numberOfNodes myTree
=> 3
Live Demo
The error indicates that you did not make a data constructor Node. Perhaps you made a data constructor Tree, for example:
data Tree a = Null | Tree a (Tree a) (Tree a)
using Tree as a data constructor is not wrong. But you need to decide what the name will be, and use that data constructor.
Anyway, you do not need to define a function to count the number of elements yourself. You can let Haskell make it an instance of Foldable, and then use length :: Foldable f => f a -> Int:
{-# LANGUAGE DeriveFoldable #-}
data Tree a = Null | Node a (Tree a) (Tree a) deriving (Foldable, Show)
If we for example define a sample tree like #AndyG wrote, we can calculate the number of Nodes as:
Prelude> length (Node 0 (Node 1 Null Null) (Node 2 Null Null))
3
If you implement the length yourself, you should make a recursive call to the subtrees, since you can not add up subtrees:
numberOfNodes :: Tree -> Int
numberOfNodes Null = 0
numberOfNodes (Node _ st1 st2) = 1 + numberOfNodes st1 + numberOfNodes st2
It seems you don't have the data type definition in scope. It should probably be
data Tree a = Null | Node a (Tree a) (Tree a)
Also, the code you show computes a tree's depth (in principle, after it's fixed). The total count of tree's nodes is the sum of the counts of nodes in its left and right sub-trees, give or take 1; not max.
Empty (leaf, Null) nodes should probably not be counted, i.e. their contribution to the total count should probably be 0. You decide.
So I have a tree defined as follows:
data Tree = Node Tree Int Tree | Leaf Int
The Int for a Node in this case is the value at that Node. I am trying to check that a tree is balanced, and that the tree is increasing as it's traversed left to right.
To do so I have a recursive function that takes a (Node left x right) and checks that the difference in height of left and right (the nodes below it) is no more than one. I then call balanced again for left and right.
Is it possible to access the Int value of left and right?
Yes, you can write a function that returns the integer at the top node:
getInt (Node _ i _) = i
getInt (Leaf i) = i
E.g.
Prelude> getInt $ Leaf 42
42
Prelude> getInt $ Node (Leaf 42) 123 (Leaf 1337)
123
Of course you can, instead of put variables like left and right, use the constructors again:
Edit, I forget the case of Leaf, it has also an int:
data Tree = Node Tree Int Tree | Leaf Int
exampleSumNodes (Node left x right) = (treeToInt left) + x + (treeToInt right)
treeToInt (Node _ n _) = n
treeToInt (Leaf n ) = n
Assume I have a binary tree:
data Bst a = Empty | Node (Bst a) a (Bst a)
I have to write a function that searches for a value and returns the number of its children. If there is no node with this value, it returns -1. I was trying to write both BFS and DFS, and I failed with both.
Pattern matching is your friend. Your Bst can either be Empty or a Node, so at the toplevel, your search function will be
search Empty = ...
search (Node left x right) = ...
Can an Empty tree possibly contain the target value? With a Node the target value, if present, will be either the node value (x above), in the left subtree, in the right subtree—or perhaps some combination of these.
By “return[ing] the number of its children,” I assume you mean the total number of descendants of the Bst rooted at a Node whose value is the target, which is an interesting combination of problems. You will want another function, say numChildren, whose definition uses pattern matching as above. Considerations:
How many descendants does an Empty tree have?
In the Node case, x doesn’t count because you want descendants. If only you had a function to count the number of children in the left and right subtrees …
Here is a way to do this. Breath-first search can actually be a bit tricky to implement and this solution (findBFS) has aweful complexity (appending to the list is O(n)) but you'll get the gist.
First I have decided to split out the finding functions to return the tree where the node element matches. That simplifies splitting out the counting function. Also, it is easier to return the number of elements than the number of descendants and return -1 in case not found, so the numDesc functions rely on the numElements function.
data Tree a = Empty
| Node a (Tree a) (Tree a)
numElements :: Tree a -> Int
numElements Empty = 0
numElements (Node _ l r) = 1 + numElements l + numElements r
findDFS :: Eq a => a -> Tree a -> Tree a
findDFS _ Empty = Empty
findDFS x node#(Node y l r) | x == y = node
| otherwise = case findDFS x l of
node'#(Node _ _ _) -> node'
Empty -> findDFS x r
findBFS :: Eq a => a -> [Tree a] -> Tree a
findBFS x [] = Empty
findBFS x ((Empty):ts) = findBFS x ts
findBFS x (node#(Node y _ _):ts) | x == y = node
findBFS x ((Node _ l r):ts) = findBFS x (ts ++ [l,r])
numDescDFS :: Eq a => a -> Tree a -> Int
numDescDFS x t = numElements (findDFS x t) - 1
numDescBFS :: Eq a => a -> Tree a -> Int
numDescBFS x t = numElements (findBFS x [t]) - 1
When I compile the following code with GHC (using the -Wall flag):
module Main where
data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show)
insert :: (Ord a) => a -> Tree a -> Tree a
insert x EmptyTree = Node x EmptyTree EmptyTree
insert x (Node a left right)
| x == a = Node a left right
| x < a = Node a (insert x left) right
| x > a = Node a left (insert x right)
main :: IO()
main = do
let nums = [1..10]::[Int]
print . foldr insert EmptyTree $ nums
GHC complains that pattern matching in insert is non-exhaustive:
test.hs|6| 1:
|| Warning: Pattern match(es) are non-exhaustive
|| In an equation for `insert': Patterns not matched: _ (Node _ _ _)
Why is GHC issuing this warning? It is pretty obvious that the pattern GHC complains about is handled in insert x (Node a left right).
It's because the pattern matching is incomplete. There's no guarantee that one of x==a, x<a, or x>a holds. For instance, if the type is Double and x is NaN then none of them are True.
Riccardo is correct, GHC doesn't infer that your guards can't possibly all be false. So accept his answer please.
I'm going to digress and talk about coding style.
Your motivation for not using otherwise may have been that it looks unsightly:
insert :: (Ord a) => a -> Tree a -> Tree a
insert x EmptyTree = Node x EmptyTree EmptyTree
insert x (Node a left right)
| x == a = Node a left right
| x < a = Node a (insert x left) right
| otherwise = Node a left (insert x right)
Looking at this code, a human reader must confirm to themselves that the final guard accepts precisely those cases where x > a.
We could instead write it like this:
insert :: (Ord a) => a -> Tree a -> Tree a
insert x EmptyTree = Node x EmptyTree EmptyTree
insert x (Node a left right) = case x `compare` a of
EQ -> Node a left right
LT -> Node a (insert x left) right
GT -> Node a left (insert x right)
The Ordering type returned by compare has only the three values EQ, LT, and GT, so GHC can confirm that you've covered all possibilities, and a human reader can easily see that you've covered them correctly.
This is also more efficient code: we call compare once, instead of calling == and then probably calling < as well.
Now I'm going to digress some more and talk about laziness.
You've probably also written a function similar to this:
contains :: (Ord a) => a -> Tree a -> Bool
contains _ EmptyTree = False
contains x (Node a left right) = case x `compare` a of
EQ -> True
...
When x == a, you need to know that the tree uses the Node constructor, and that its first argument is equal to x. You don't need to know what either of the subtrees are.
But now look back at my definition of insert above. When the tree it's given is a Node, it always returns a Node whose first argument is always a. But it doesn't state that up front: instead it evaluates x `compare` a.
We can rewrite insert to perform the comparison as late as possible:
insert :: (Ord a) => a -> Tree a -> Tree a
insert x EmptyTree = Node x EmptyTree EmptyTree
insert x (Node a left right) = Node a newLeft newRight
where comparison = x `compare` a
newLeft = if comparison == LT then insert x left else left
newRight = if comparison == GT then insert x right else right
Now we return the Node a bit as soon as possible --- even if the comparison throws an error! --- and we still perform the comparison once at most.
GHC is not able to infer whether your three guards in the insert x (Node a left right) cover all possible cases, and consequently there will be no body to be associated with insert x (Node a left right). Try replacing the last condition x > a with otherwise (a synonim for True).
In this specific case however, it's true that the guards do not cover all cases, see augustss' example about double numbers.