Traversing a tree, predecessor and successor - data-structures

I am facing a couple of doubts in tree data structure.
1) Is tree traversing (Preorder, Inorder, Postorder) possible in all types of trees or only binary trees.
2) If the first point is valid, then can we simply Inorder traverse a tree and store the elements in an array.
And then by using that array can we find predecessor and successor, as elements coming before and after a given element.

1.
Tree traversing (Preorder, Inorder, Postorder) possible in all types of trees
not only in binary trees.
every tree contains child nodes.( binary tree 2, ternary tree 3 etc).
We need to define our own way of traversing the trees.
lets take example of ternary tree.
Preorder : visit(root.data) - >root.left -> root.middle -> root.right
postorder: root.left -> root.middle - > root.right -> visit(root.data)
inorder : root.left -> root.middle -> visit(root.data) - > root.right
Preorder : visit all k child nodes( from left to right) after first visiting root node.
Postorder : visit all k child nodes (from left to right) before visiting root node.
Inorder : visit k/2 child nodes( from left to right) and visit root node then visit remaining k/2 child nodes.
we can store the tree in an array by inorder traversing.
we can find the predecessor and successor from that array by how we did inorder traversal.
for a binary tree, predecessor = left child, successor = right child
for ternary tree, predecessor = left child or middle child , successor = middle child or right child. ( we have to specify it based on our requirement)

Related

Binary tree preorder visit pseudocode

Have been searching on web for more than 5 hours and cant find a general BT Preorder visit pseudocode.
Thanks in advance.
I just find short pseudocodes like this
Algorithm postorder(T, v)
Input: A binary tree T and a node v of T.
Output: Depends on the action performed on a visit to a node.
if T.hasLeft(v)
postorder(T, T.left(v)) // recursively traverse left subtree
if T.hasRight(v)
postorder(T, T.right(v)) // recursively traverse right subtree
visit node v
The difference between preorder, inorder, and postorder is simply the order in which the nodes are visited, relative to the children:
You posted this:
Algorithm postorder(T, v)
Input: A binary tree T and a node v of T.
Output: Depends on the action performed on a visit to a node.
if T.hasLeft(v)
postorder(T, T.left(v)) // recursively traverse left subtree
if T.hasRight(v)
postorder(T, T.right(v)) // recursively traverse right subtree
visit node v
To change among the behaviors, change the order of execution. Here's some generic code:
AnyOrder:
AnyOrder(T, v, order)
if order is 'pre'
visit(v)
AnyOrder(T, T.left(v), order)
if order is 'in'
visit(v)
AnyOrder(T, T.right(v), order)
if order is 'post'
visit(v)

Data Structures: Binary tree traversal

Hi I'm a bit confused with this tree and need help in figuring out if I'm choosing the right answer.
Tree :
A
/ \
B C
/ \
D E
Lets do the traversal first:
In-order : BADCE
Pre-Order : ABCDE
Post-Order : BDECA
Questions:
Which of the following traversals yields BADEC?
a. only in-order
b. only level order
c. only post-order
d. only pre-order
e. pre-order and level order
f. in-order and level order
g. none of the above
Answer g
Which of the following is a post-order traversal of the BST?
a. ACEDB
b. ABDCE
c. BDECA
d. EDCBA
e. BADCE
f. BADEC
g. one of the above
Answer g
Can someone please confirm if I have done the traversal correctly and have chosen the correct answer for both question.
Thanks
The three traversal algorithms is a recursive algorithm. This means that in order to traverse the entire tree rooted at node A, the algorithm will split and finish the task in three parts:
traverse the subtree rooted at B (A's left child)
traverse the subtree rooted rooted at C (A's right child)
traverse/visit A itself
The order of the three tasks depends on which order you use:
- In-order (Left, Root, Right) does task1, task3, and then task2. - Pre-order (Root, Left, Right) does task3, task1, and then task2. - Post-order (Left, Right, Root) does task1, task2, and then task3
Continue the recursive algorithm: to traverse the subtree rooted at B, it will split the task further and traverse the subtree rooted at B's left child, the subtree rooted at B's right child, and then B.
The "splitting task" continues until the subtree to traverse contains only one root node. In this case, the algorithm visits the root node and returns to the remaining sub-tasks. Same thing happens to the subtree rooted at C, A's right child.
Here are the detailed steps to traverse the tree in the question in 3 different orders and to answer the questions using the traversal results:
In-order traversal (Left, Root, Right):
traverse subtree rooted at B
visit B
visit A
traverse subtree rooted at C
traverse C's left subtree
visit D
visit C
traverse C's right subtree
visit E
In-order: BADCE
Pre-order traversal (Root, Left, Right)
visit A
traverse subtree rooted at B
visit B
traverse subtree rooted at C
visit C
traverse C's left subtree
visit D
traverse C's right subtree
visit E
Pre-order: ABCDE
Post-order traversal (Left, Right, Root)
traverse subtree rooted at B
visit B
traverse subtree rooted at C
traverse C's left subtree
visit D
traverse C's right subtree
visit E
visit C
visit A
Post-order: BDECA
You can check if your traversal results are the same as above.
Looking at the traversal results, we know that the answer to your question 1 is g, and the answer to your question 2 is c.

Given a binary tree, count the number of binary search trees present in it

A binary tree is given and we have to count the number of binary search trees in it.Every leaf node is a BST
I used the following approach.
for every node in bt check if it is bst or not
The time complexity for above approach is O(n2).How can we do it in an efficient way O(n).
If I understood the question correctly, this can be solved as follows; one would aim at counting the number of nodes which are the root of a binary seach tree. As already remarked, every leaf is trivially the root of a binary search tree. A non-leaf node a is the root of a binary search if and only if the left child of a is a binary search tree, the right child of b is the root of a binary search tree and the maximum over all values under the left child of a is not greater than the value of a and the minumum over all values under the right child of a are larger or equal to the value of a. Evaluation of this property can be done by a recursive evaluation which visits every node exactly once, which results in a linear runtime bound.
A straightforward recursive traversal of the tree returning a few extra pieces of data may help manage it in O(n) time, n being the number of nodes. Below you can find an implementation in Python.
numBST = 0
def traverse(root):
global numBST
leftComplies = True
rightComplies = True
rootRange = [root.val, root.val]
if root.left != None:
leftResult = traverse(root.left)
leftComplies = leftResult[0] and leftResult[1][1] < root.val
rootRange[0] = leftResult[1][0]
if root.right != None:
rightResult = traverse(root.right)
rightComplies = rightResult[0] and rightResult[1][0] > root.val
rootRange[1] = rightResult[1][1]
if leftComplies and rightComplies:
numBST += 1
return (leftComplies and rightComplies, rootRange)
After you run traverse with root of the binary tree as parameter, numBST will contain the number of BSTs within the root.
The function traverse given above recursively traverses the tree root of which is given to it as a parameter. For each node V, if V has a left child L, it recursively traverses the left child and returns some data. Specifically, it returns a list of length 2. The first element in the list is a boolean value indicating whether the left subtree rooted in L is a BST. Second element of the returned list contains another list containing the smallest and the largest value, respectively, in the subtree rooted in L.
For the tree rooted in V to be a BST, the subtree rooted in L must also be a BST AND the largest value in the subtree rooted in L(hence all the values in that subtree) must be smaller than the value stored in V. So after recursively calling traverse for L, we check the returned data to find out if these conditions are satisfied.
Similarly, if there is a right child R of V, it is recursively traversed. To be a BST, the tree rooted in V must also satisfy the condition that the tree rooted in R is a BST AND the smallest node of subtree rooted in R(hence all the nodes in that subtree) contains a value that is larger than the value stored in V.
If all these conditions are satisfied, the tree rooted in V can be considered as a BST and the result, stored in numBST, is updated accordingly. Note that we also update the smallest and largest values stored in V as we recursively traverse its children L and R, and perform the checks mentioned above, so that we pass the correctly updated values to the higher levels of recursion.

Finding all subtrees of n-ary tree

I am trying to find all subtrees of n-ary tree. Only BFS or DFS does not work. Because the tree is not binary. For example:
1
/ \
2 3
/ \ /|\
4 6 5 7 8
/ \
9 10
I want to show all subtrees including this one
1
/ \
2 3
\ |
6 7
How can I extract this subtree from original one?
To generate all (graph-theoretic) subtrees of a given tree, I will need some auxiliary notions.
A subtree is a connected subgraph pf a tree, or equivalently, a subgraph which is also a tree.
A descendant tree of a rooted tree is either the original rooted tree itself, or a rooted tree which is a child of one of its vertices. (Won't give an exact definition here as it should be clear from the notion of a tree as a recursive data structure).
A rooted subtree of a rooted tree is a subtree that has the same root as the original rooted tree. We can get a rooted subtree of a rooted tree by computing rooted subtrees of (some of) immediate children of the root, and combining those with the original root.
Note that an arbitrary subtree is a rooted subtree of a descendant tree.
I will deal with non-empty trees for simplicity.
-- a (rooted) tree is a root node and a list of children attached to it
data Tree a = Node a [Tree a] deriving Show
It is straightforward to get the descendants:
-- a descendant tree is either a tree itself,
-- or a descendant of a child of its root
descendants :: Tree a -> [Tree a]
descendants t#(Node a ts) = t : concatMap descendants ts
Rooted subtrees are not much harder:
-- to get a rooted subtree, take a root, choose which children to
-- retain, take a rooted subtree of each retained child,
-- and attach the results to a copy of the root
rootedSubtrees :: Tree a -> [Tree a]
rootedSubtrees (Node a ts) = [Node a tts |
tts <- choices (map rootedSubtrees ts)]
-- this function receives a list of lists and generates all lists that
-- contain 0 or 1 element from each input list
-- for ex. choices ["ab", "cd"] = ["","c","d","a","ac","ad","b","bc","bd"]
choices :: [[a]] -> [[a]]
choices [] = [[]]
choices (xs:xxs) = cs ++ [x:c | x <- xs, c <- cs] where cs = choices xxs
Finally, the list of arbitrary subtrees is
subtrees :: Tree a -> [Tree a]
subtrees t = concatMap rootedSubtrees (descendants t)
You could do the following.
For each vertex in the tree you decide whether to cut the subtree with root the vertex or to keep exploring. Your number of choices is ~2^(number of nodes). Note it is note exactly 2^(number of nodes) (it's less but still exponential) since after you cut a subtree you don't explore it.
For each configuration of choices for each vertex print the tree using DFS.
Your example is the configuration in which the subtree with roots 4, 5, 8 were cut.
The cuts could be done implicitly by having flags for each node.

Given binary tree represented as an array, find the pre-order traversal of it

Given a binary tree represented as the array [_,21,18,19,7,3,8,5,2,1]. What is the result of the pre-order traversal of this tree? The _ indicates an empty location in the array.
I'm confused by this because the tree can have more than one configuration, right? So, the pre-order traversals can be different. There is a "none of the above" answer.
In a binary tree represented as an array, a, typically the root is at a[1]. Given a node at position x, its left child is at a[x*2] and its right child is at a[(x*2)+1]. So the root's left child is at a[2] and its right child is at a[3].
The left child of the node at a[2] is at a[4], and the right child of the node at a[3] is at a[7].
For a node at position x, its parent is at a[x/2].
Given that, you should be able to construct your tree from that array. And then you can easily determine the preorder traversal.

Resources