Finding all subtrees of n-ary tree - algorithm

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.

Related

Is a height-balanced tree a tree where a node with exactly one child must have a leaf as its only child?

https://en.wikipedia.org/wiki/Binary_tree#Types_of_binary_trees says:
A balanced binary tree is a binary tree structure in which the left and right subtrees of every node differ in height by no more than 1.
Is it equivalent to say that a binary tree is height-balanced if a node with exactly one child must have a leaf as its only child?
Is it equivalent to say that a binary tree is height-balanced if a node with exactly one child must have a leaf as its only child?
No. This is a correct observation about balanced binary trees, but it is not a complete definition of balanced binary trees. While all balanced trees have this property, it is easy to produce unbalanced trees that also have this property.
To start, your observation is correct when applied to balanced trees:
In a binary tree, a node with only one child still has two subtrees, one of which is empty and has a height of 0. By definition, in a balanced binary tree, the other non-empty subtree must have a height of 0 or 1. So, if the node has one child, then that child is necessarily a leaf node with a subtree height of 1, resulting in subtree heights of 0 and 1. Anything but a leaf node is an unbalanced tree with subtree heights of 0 and >1.
For example, consider a node A which has as its left child a leaf node B, and no right child:
A
/
B
The heights of A's left subtree is 1, and its right subtree is 0, so this is a balanced tree: The difference in heights is 1.
If A continues to have a single child B, and any node exists under B such that it is not a leaf, then A's left subtree height becomes greater than 1, while the right subtree height remains 0:
A
/
B
/
C
This is by definition not a balanced tree.
However, it is possible, and easy, to produce an unbalanced binary tree that still satisfies your modified definition:
a binary tree is height-balanced if a node with exactly one child must have a leaf as its only child?
The following tree satisfies this criteria: The only node with 1 child, D, has a leaf node as its child. However, the tree is clearly not balanced:
A
/ \
B C
/ \
D E
/
F
You could extend the left subtree indefinitely, and it would still satisfy your criteria; only the second to last node needs to have one child which is a leaf, all other nodes have either 0 or 2 children.
A
/ \
B C
/ \
D E
/ \
F G
/ \
H I
/ \
J K
/
L

Traversing a tree, predecessor and successor

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)

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.

Is it possible to create a binary non-unique tree using the preorder and postorder sequences?

Is it possible to create a binary non-unique tree using the preorder and postorder sequences ?If so, how can this be done ? For example how could I make a non-unique tree for:
Preorder:
B C I J K H D E F G
Postorder:
I H K J C G F E D B
How many could there be ?
preorder psedo-code:
preorder (tree)
{
if tree isn't empty then
{
print key[tree]
preorder left[tree]
preorder right[tree]
}
}
and post order is:
postorder (tree)
{
if tree isn't empty then
{
preorder left[tree]
preorder right[tree]
print key[tree]
}
}
so from inorder order we can conclude:
"B" must be the root
"C" must be "B"'s child
"G" must be the the max value (the most far right node in the tree) or the min value in the left sub-tree (the most far left node in the left sub-tree) - in that case "G" must be a leaf and "F" must be "G"'s parent
and from postorder order we can conclude:
"I" must be a leaf and the min value (the most right node in the tree).
"H" must be "I"'s parent ("I" is "H" left child) in case I has no children, else "H" is the next far left child in the tree.
from here it's like a Sudoku:
and yes: by using preorder and postorder outputs you can build a tree in only one way.
Yes, it is possible to construct different binary trees that have the same pre- and postorder sequences. To generate such different trees, look for subtrees where either the left or the right child is empty and simply swap the children.
This minimal example
a a
/ vs. \
b b
shows two trees that both have the preordering a b and the postordering b a.

reconstructing a tree from its preorder and postorder lists

Consider the situation where you have two lists of nodes of which all you know is that one is a representation of a preorder traversal of some tree and the other a representation of a postorder traversal of the same tree.
I believe it is possible to reconstruct the tree exactly from these two lists, and I think I have an algorithm to do it, but have not proven it. As this will be a part of a masters project I need to be absolutely certain that it is possible and correct (Mathematically proven). However it will not be the focus of the project, so I was wondering if there is a source out there (i.e. paper or book) I could quote for the proof. (Maybe in TAOCP? anybody know the section possibly?)
In short, I need a proven algorithm in a quotable resource that reconstructs a tree from its pre and post order traversals.
Note: The tree in question will probably not be binary, or balanced, or anything that would make it too easy.
Note2: Using only the preorder or the postorder list would be even better, but I do not think it is possible.
Note3: A node can have any amount of children.
Note4: I only care about the order of siblings. Left or right does not matter when there is only one child.
Preorder and postorder do not uniquely define a tree.
In general, a single tree traversal does not uniquely define the
structure of the tree. For example, as we have seen, for both
the following trees, an inorder traversal yields [1,2,3,4,5,6].
4 3
/ \ / \
2 5 2 5
/ \ \ / / \
1 3 6 1 4 6
The same ambiguity is present for preorder and postorder
traversals. The preorder traversal for the first tree above is
[4,2,1,3,5,6]. Here is a different tree with the same preorder
traversal.
4
/ \
2 1
/ \
3 6
\
5
Similarly, we can easily construct another tree whose postorder
traversal [1,3,2,6,5,4] matches that of the first tree above.
You cannot use only one list, because you'll get no sense of the depth of the tree. Thus, you definitely require two or more lists.
Here's my attempt at a solution:
Use your preorder traversal as a means of knowing the ordering of the data. This makes sense because you know the first node is the top, and you know that data further to the left of the traversal belongs to the left of the tree, etc.
Your post order traversal can determine the depth of the tree. For example, let's say I have a structure like this:
1
2 5 6
3 4 7
Where 2 is the parent of 3 and 4, and 5 is the parent of 7.
Preorder: 1 2 3 4 5 7 6
Postorder: 3 4 2 7 5 6 1
We know we start with 1, because it is the first node in the preorder traversal. Then we look at the next number, 2. In the post order, because the number 2 comes BEFORE node 1, we know that 2 has to be a child of 1. Next we look at 3. 3 comes before 2, and thus 3 is a child of 2. 4 is before 2 but after 3, so we know 4 is a child of 2 but NOT a child of 3. Etc.
Now, this may not work if the nodes are not unique, but at the very least its a start to a solution.
Edit: The order of the children is preserved with this solution, simply due to knowing the ordering of the nodes via the preorder traversal, and then knowing the structure via the postorder traversal.
Edit2: The proof may lie here: http://ieeexplore.ieee.org/Xplore/login.jsp?url=http%3A%2F%2Fieeexplore.ieee.org%2Fiel2%2F215%2F626%2F00017225.pdf%3Farnumber%3D17225&authDecision=-203
I think you need to purchase the document, however...
Here is a written proof presented to be a solution:
http://www14.informatik.tu-muenchen.de/lehre/2007WS/fa-cse/tutorials/tutorial09-solutions.pdf
Consider an arbitrary tree T as the quadruple (A, B, C, D), where A is the root node, B is the root node of the first child, C is a vector of any non-empty children of B, and D is a vector of any non-empty siblings of B. The elements of C and D are themselves trees.
Any of A, B, C and D may be empty. If B is empty, so must be C and D; if A, then everything.
Since nodes are unique, the sets of nodes contained anywhere within C and D are disjoint, and neither contains A or B.
Functions pre() and post() generate ordered sequences of the form:
pre(T) = [A, B, pre(C), pre(D)]
post(T) = [post(C), B, post(D), A]
where the function applied to a vector is defined to be the concatenation of the sequences resulting from applying the function to each element in turn.
Now consider the cases:
if A is empty, the output of both functions is the empty sequence []
if B is empty, the output of both functions is just [A]
if C and D are empty, pre(T) = [A, B] and post(T) = [B, A]
if just C is empty, pre(T) = [A, B, D'] and post(T) = [B, D'', A] (where the primes indicate some permutation of the nodes contained within D)
if just D is empty, pre(T) = [A, B, C'] and post(T) = [C'', B, A]
if none are empty, pre(T) = [A, B, C', D'] and post(T) = [C'', B, D'', A]
In all cases we can unambiguously partition the members of the two output sequences into the appropriate subsequences, by using A and B (if present) as delimiters.
The question then is, can we also partition the vector sequences? If we can, then each can be recursively processed and we're done.
Since the result of pre() will always be a chain of sequences starting with A nodes, and the result of post() will always be a chain of sequences ending with A nodes, we can indeed divide them up, provided that the A nodes are never empty.
This is where the process falls down in the case of binary (or indeed any) trees with fixed children that may independently be empty. In our case, however, we have defined C and D to contain only non-empty nodes, and so the reconstruction is guaranteed to work.
Um, I think so, anyway. Obviously this is just an argument, not a formal proof!
Create a binary tree with this restriction that has at least one node that this node has only one child(right or left ,there is no difference).
Now, write its Preorder and Postorder lists. then try to reconstructing the tree from these lists. and you realize that on that node you cannot decide that its child is right or left.
The preorder and postorder traversals are sufficient to reconstruct the tree, assuming the nodes are uniquely named. The key to creating the algorithms to do so is to understand that
X is an ancestor of Y iff X precedes Y in the preorder and is after Y in the postorder.
Given this, we can always find all the descendants of any node. The descendants of X always immediately follow X in the preorder, and precede X in the postorder. So once we know we're interested in producing the subtree rooted at X, we can extract the preorder and postorder traversal for the subtree rooted at X. This leads naturally to a recursive algorithm, once we realize that the node immediately after X must be its leftmost child, if it is a descendant at all.
There is also a stack-based implementation, which iterates through the preorder nodes, and keeps on the stack any nodes which are candidates to be the direct parent of the next preorder node. For each preorder node, repeatedly pop all nodes off the stack which are not parents of the next preorder node. Make that node a child of the top node on the stack, and push the child onto the stack.
As already pointed out by others, a binary tree can not be reconstructed by using only pre and post order traversal. A single child node has ambiguous traversals that cannot identify whether it is left or right child e.g. consider following preorder and postorder traversals:
preorder: a,b
postorder b,a
It can produce both of the following trees
a a
\ /
b b
It is simply not possible to know if b is a's left or right child without any additional information like inorder traversal.
It is not possible to construct a general Binary Tree from preorder and postorder traversals (See this). But if know that the Binary Tree is Full, we can construct the tree without ambiguity. Let us understand this with the help of following example.
Let us consider the two given arrays as pre[] = {1, 2, 4, 8, 9, 5, 3, 6, 7} and post[] = {8, 9, 4, 5, 2, 6, 7, 3, 1};
In pre[], the leftmost element is root of tree. Since the tree is full and array size is more than 1. The value next to 1 in pre[], must be left child of root. So we know 1 is root and 2 is left child. How to find the all nodes in left subtree? We know 2 is root of all nodes in left subtree. All nodes before 2 in post[] must be in left subtree. Now we know 1 is root, elements {8, 9, 4, 5, 2} are in left subtree, and the elements {6, 7, 3} are in right subtree.
1
/ \
/ \
{8, 9, 4, 5, 2} {6, 7, 3}
We recursively follow the above approach and get the following tree.
1
/ \
2 3
/ \ / \
4 5 6 7
/ \
8 9

Resources