Retrieving an element of a balanced binary tree in Haskell - haskell

Assuming I have a custom tree datatype of the following form:
data BalTree a = Leaf | Node Integer (BalTree a) a (BalTree a) deriving (Eq, Show, Read)
and creating a new tree of size 10, I'll get this:
Node 10 (Node 5 (Node 2 (Node 1 Leaf 'Z' Leaf) 'Z' Leaf)
'Z'
(Node 2 (Node 1 Leaf 'Z' Leaf) 'Z' Leaf))
'Z'
(Node 4 (Node 2 (Node 1 Leaf 'Z' Leaf) 'Z' Leaf)
'Z'
(Node 1 Leaf 'Z' Leaf))
How do I retrieve an element in in-order transversal when given an index?
My attempt:
ind Leaf pos = Nothing
ind tree#(Node n lt x rt) pos
| pos < 0 = Nothing
| pos > treeSize-1 = Nothing
| pos < hTreeSize = ind lt pos
| pos == hTreeSize = Just x
| pos > hTreeSize = ind rt (pos - hTreeSize)
where treeSize = size tree
hTreeSize = treeSize `div` 2
I'm not exactly sure if this is in-order transversal and it doesn't return the correct result.

We want to get the nth value stored in a binary tree in an in-order walk. We know the number of values stored in each tree rooted at each node (the Integer parameter of Node).
data BalTree a = Leaf
| Node Integer (BalTree a) a (BalTree a)
size :: BalTree a -> Integer
size Leaf = 0
size (Node size _ _ _) = size
nthInOrder :: BalTree a -> Integer -> Maybe a
nthInOrder Leaf _ =
Nothing
nthInOrder (Node _ left x right) n
| leftSize == n - 1 = Just x
| n <= leftSize = nthInOrder left n
| otherwise = nthInOrder right (n - leftSize - 1)
where
leftSize = size left
The idea is this: suppose we're at node A and want the nth value:
A
/ \
B C
If B holds n-1 values, then the nth value is that of A. If B holds more or equal than n values, then we can ignore the rest of the tree and search only B; so we just recurse into it. Otherwise, we should be looking for the value in C, so we recurse into it; in this case, we also need to update the n to reflect that there are some values in B, and 1 value in A.
In the worst case, this algorithm walks down to a Leaf, so, the complexity is O(depth of tree). If the tree is balanced, the complexity is O(log2(size of tree)).

Related

Check if binary tree is complete - haskell

I have a binary tree:
data Btree a = Leaf a | Unary (Btree a) a | Binary (Btree a) a (Btree a) deriving Show
and some examples to work with:
ex1 = Binary (Binary (Leaf 0) 1 (Leaf 2)) 3 (Unary (Leaf 4) 5)
ex2 = Binary (Unary (Leaf 1) 2) 3 (Binary (Leaf 4) 5 (Leaf 10))
ex3 = Binary (Binary (Leaf (0,"a"))(1,"z")(Leaf (2,"x")))(3,"y")(Binary (Leaf (4,"b"))(5,"c")(Leaf (6,"d")))
I need to find out whether the tree is complete or not, a tree is complete if the distance between the root and any leaf is always the same up to 1, all of the deepest leaves are located to the left of the others, and there is at most one internal node with unary node that should be located on the second-to-last level.
This is what i have so far
complete :: Btree a -> Bool
complete x = fst $ go x where
go (Leaf _) = (True, 0)
go (Unary left _) = (leftTrue, 1 + leftCount) where
(leftTrue, leftCount) = go left
go (Binary left _ right) = (leftTrue && rightTrue &&
leftCount == rightCount,
1 + leftCount + rightCount) where
(leftTrue, leftCount) = go left
(rightTrue, rightCount) = go right
ex1 & ex3 should return true, but only ex3 is. I believe the Unary part is the issue.
This answer counts on a code change in the Unary part like that: (leftTrue, 1 + leftCount) -> (False, 1 + leftCount).
The body of your solution is the go function.
The function returns for a subtree
if the left and right subtrees are completely balanced and how many nodes the subtree has.
All depths are the same, like in the ex3.
But if you don't have 2^n-1 nodes and 2^(n-1) leaves, it is impossible to build that tree.
In the description of your problem is allowed little disbalance allowing represent any count of nodes.
Ex1 fulfills the rules ex2 doesn't.
Ex3 is also complete according to your definition.
Under the code, I made ASCII art to the examples.
My solution doesn't count amount nodes of subtrees. It calculates maximal and minimal depths because it allows me to reveal illegal disbalance in any level of a tree.
The boolean value says if the subtree accomplishes your conditions of the complete tree.
It checks that:
differences are the same up to one
the left subtree has a greater or the same minimal depth as the maximal depth of the right tree.
Checks above also contain the condition about one unary node on the second-to-last level.
Can you guess what belongs to the place ...?
data Btree a = Leaf a | Unary (Btree a) a | Binary (Btree a) a (Btree a) deriving Show
ex1 = Binary (Binary (Leaf 0) 1 (Leaf 2)) 3 (Unary (Leaf 4) 5)
ex2 = Binary (Unary (Leaf 1) 2) 3 (Binary (Leaf 4) 5 (Leaf 10))
ex3 = Binary (Binary (Leaf (0,"a"))(1,"z")(Leaf (2,"x")))(3,"y")(Binary (Leaf (4,"b"))(5,"c")(Leaf (6,"d")))
complete :: Btree a -> Bool
complete x = fst $ go x
go :: Btree a -> (Bool,(Int,Int))
go (Leaf _) = (True, (0, 0))
go (Unary left _) = (leftMaxDepth == 0, (1 + leftMaxDepth, 0)) where
(leftIs, (leftMaxDepth, leftMinDepth)) = go left
go (Binary left _ right) =
( leftIs && rightIs
...
, (1+newMaxDepth
, 1+newMinDepth )) where
newMaxDepth = max leftMaxDepth rightMaxDepth
newMinDepth = min leftMinDepth rightMinDepth
(leftIs, (leftMaxDepth, leftMinDepth)) = go left
(rightIs, (rightMaxDepth, rightMinDepth)) = go right
&& leftMinDepth >= rightMaxDepth && newMaxDepth - newMinDepth <= 1
ex1: True
3
/ \
/ \
1 5
/ \ /
0 2 4
Depths: [3,3,3,2]
ex2: False
3
/ \
/ \
2 5
/ / \
1 4 10
Depths: [3,2,3,3]
ex3: True
(3,"y")
/ \
/ \
(1,"z") (5,"c")
/ \ / \
(0,"a") (2,"x") (4,"b") (6,"d")
Depths: [3,3,3,3]
This answer counts on a code change in the Unary part like that: (leftTrue, 1 + leftCount) -> (False, 1 + leftCount).
https://web.cecs.pdx.edu/~sheard/course/Cs163/Doc/FullvsComplete.html
Full binary rtee:
Complete binary tree:
Your solution counts on a full binary tree.
Your exercise is about checking if the binary tree is complete.
The algorithm is fine, but the check leftCount == rightCount should be changed.
A full binary tree has a minimum depth equal to the maximum depth,
and the left subtree has the same number of nodes as the right.
In a complete binary tree, the situation is more difficult:
Let the number of nodes complete binary tree is x then
x = 2^m-1+n, where m is the minimum depth of the tree and 0 <= n < 2^(m+1) .
Let '1' be the suffix of the left subtree and the suffix '2' of the right.
for subtrees of a complete binary tree, it always holds:
If the minimum depths of the left and right subtrees are the same, then the right tree must be full.
If the minimum depth of the left subtree is equal to the minimum depth of the right subtree plus one, then the left subtree must be full.
getMinDepthAndRest :: Int -> (Int,Int)
getMinDepthAndRest x = getMinDepthandRest' x 0
getMinDepthAndRest' :: Int -> Int -> (Int,Int)
getMinDepthAndRest' x m'
| x < 2^m'-1 = (m'-1,x-2^(m'-1)+1)
| otherwise = getMinDepthandRest' x (m'+1)
complete :: Btree a -> Bool
complete x = fst $ go x where
go (Leaf _) = (True, 1)
go (Unary left _) = (leftCount == 1, 1 + leftCount) where
(leftTrue, leftCount) = go left
go (Binary left _ right) = (leftTrue && rightTrue &&
(m1==m2 && n2==0) || (m1==m2+1 && n1==0),
1 + leftCount + rightCount) where
(m1,n1) = getMinDepthAndRest leftCount
(m2,n2) = getMinDepthAndRest rightCount
(leftTrue, leftCount) = go left
(rightTrue, rightCount) = go right

Tree Traversal - DFS

I need to implement a DFS traversal on a Tree with a maximum depth ( so for example if the depth is 0 then you only show the root ).
successors node will return a list of (Int,Tree) where Tree is basically the "s" in my Node s a
limitedDfsRec :: (ProblemState s a, Ord s, Ord a) => [Node s a] -> Int -> S.Set (Node s a)-> [Node s a] -> [Node s a]
limitedDfsRec [] _ _ result = reverse result
limitedDfsRec (node:coada) max_depth visited result | adancime node > max_depth = limitedDfsRec coada max_depth visited result
| S.member node visited = limitedDfsRec coada max_depth visited result
| otherwise =
let succesori = [(Nod copil (Just actiune_copil) (Just $ stare node) ((adancime node) + 1) []) | (actiune_copil,copil) <- successors (stare node)]
in limitedDfsRec (succesori ++ coada) max_depth (S.insert node visited) (node : result)
You start from a node,if it's depth is greater than the maximum depth allowed you go to next element in the list (coada).
If the element is already visited then you go to the next element in the list.
Else,you get all the children (succesori) and put them in the list (coada),you add the element to the visited and to the final result.
That function is used toghether with this one :
instance ProblemState Tree Int where
successors (Tree n)
| n == 2 = [(1, Tree 4), (2, Tree 6)] -- 4 instead of 5 => cycle
| otherwise = [(1, Tree $ 2 * n + 1), (2, Tree $ 2 * n + 2)]
isGoal (Tree n) = n == 13
Which generates the children. Well,the problem is that the function above still visits nodes even if they are in the visited set and I don't understand why.
So,for example, starting from Tree 0 with a maximum depth of 2 you should get [0,1,3,4,2,6] but my function gets [0,1,3,4,2,4,6] because when it gets to 2 it puts 4 and 6 in the list but when it gets to 4 it sees that 4 was not visited yet and puts it in the output (result).
I want to see the problem with THIS code,not other ways it works because I need to use this on more than 2 children.
You're keeping whole nodes in the visited set
| S.member node visited = ...
-- ^ Node s a
So you can have multiple nodes labeled by 4 but with different extra information.
You probably only want a visited :: S.Set s.

Update a tree based on index Haskell

I have trees of the form:
data Tree a = Leaf | Node (Tree a) a (Tree a)
I created a function to look up the value of a node in a tree based on an in-order, left-to-right traversal.
getElem :: Tree a -> Int -> Maybe a
getElem Leaf _ = Nothing
getElem (Node l x r) n
| s == n = Just x
| n < s = getElem l n
| otherwise = getElem r (n - s - 1)
where
s = size l
I now want to write a method to be able to update a tree. It should be able to take in a tree, an index and a value and update the node at that index with the value. So far I have:
update :: Tree a -> Int -> a -> Tree a
update Leaf _ _ = Leaf
update (Node l x r) index c
| s == index = (Node l c r)
| index < s = update l index c
| otherwise = update r (index - s - 1) c
where
s = size l
This function is able to add but it obviously returns just the added node itself. I want to be able to return the entire tree post the 'update' with the new node or return the tree as is if the index is out of bounds.
Could anybody give me some idea how to proceed with this?
Edit 1:
Okay, I understand that I am basically discarding the remainder of my tree when recursing here. So:
update :: Tree a -> Int -> a -> Tree a
update Leaf _ _ = Leaf
update (Node l x r) index c
| s == index = (Node l c r)
| index < s = update (Node l2 x r) index c
| otherwise = update (Node l x r2) (index - s - 1) c
where
s = size l
l2 = l
r2 = r
Edit 2(Silly me!):
update :: Tree a -> Int -> a -> Tree a
update Leaf _ _ = Leaf
update (Node l x r) index c
| s == index = (Node l c r)
| index < s = (Node (upd l index c) x r)
| otherwise = (Node l x (upd r (index - s - 1) c))
where
s = size l
It took me a bit to wrap my head around it. Thank you for the comments!
Since in Haskell all data is immutable, you can not "update" a tree, you construct a new tree. That tree might however have references to subtrees of the old tree. You thus do not per se construct a completely new tree.
You managed to create an "updated" node, so now the only thing that is missing, is to use the "updated" subtree in a new tree. In that tree, you can use the "old" value together with the other subtree to construct a new one, like:
update :: Tree a -> Int -> a -> Tree a
update Leaf _ _ = Leaf
update (Node l x r) index c
| s == index = Node l c r
| index < s = Node (update l index c) x r
| otherwise = Node l x (update r (index - s - 1) c)
where s = size l
You might also need to change the Leaf case if you "count" a leaf as a node.
Trees with indices are not very common. It might also - in order to boost performance - be better to keep track of the number of items in the left subchild (or both), since then we can just pick the left or right subchild without counting the children. By keeping track of the number, for a complete tree, then updating the tree is an O(log n) operation, not an O(n) operation.

(Can I?) How can I access the int value of the next node (tree recursion)

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

Finding element in a binary tree

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

Resources