I am in the process of converting recursive function for a BST to non recursive to help prepare for an interview. So far I figured out preorder, inorder, postorder, search, delete, insert, and converting the BST to a circular linked list. I am having trouble figuring out how to use stack or queues to get the height and to find if it is a BST. Any tips would be greatly appreciated. I am not looking for code but the logic behind the code.
For starters, great job preparing for interviews like this! I hope that you're having fun playing around with these algorithms.
Let's begin with the task of trying to determine if the binary tree is a BST. One way of doing this is to do an inorder walk of the tree and check if the elements are in sorted order. This will be true if and only if the tree is a BST. Since you already have code to do an inorder walk of the elements of the tree, you should be able to easily adapt your code to check if the elements that come out of the inorder walk are sorted by keeping track of the last element you saw in the inorder walk, then comparing each element generated to the previous element. If the two are out of order, the tree is not a BST.
To determine the height of the tree, one option would be to take any of the searches that you've come up with so far (preorder, postorder, inorder) and keep track of the height of the stack at each point. The idea here is that since your stack will always keep track of the path back from any node up to the root, you can simply walk the tree and record the deepest that you ever saw the stack become. This maximum depth is then the height of the tree.
Hope this helps! And best of luck with interviews!
To find the height of the tree, you could use the Morris traversal [ O(n) time]].
To check if it is a valid BST, do an inorder walk of the tree.
Move the elements into an array. Check if the array is sorted or not to validate a BST.
Related
I have to create and describe an algorithm for my university course that gets a BST tree T and creates new BST tree T' that satifies properties (and is as fast as possible):
1) T' has the same exact key values as T
2) T' is a Red-Black tree
So far I've had only one idea: randomize 0 or 1. In case of 0, get the max key node from left subtree of T and insert it into T', otherwise get the min key node from right subtree of T and insert it into T'. This is to ensure that Red-Black tree is at least somewhat balanced. The insertion would be any standard RB insertion.
Complexity of getting min/max is O(h), and since this needs to be repeated for each of the nodes in T, this would get quite high. I could also keep a pointer at the max node of left subtree and min node of the right subtree, which would solve the problem of traversing the whole height of the tree every time.
What do you think about this solution? I'm pretty sure it can be done better. Sorry if there is an obvious better solution, but I couldn't find answer to this on the internet, also it's only my 2nd semester at the university and I don't have much experience with programming.
Unless you have some other constraints or information, the fastest way is to forget about the shape of the original BST.
Just put the keys in an ordered list, and build a complete binary tree from it, all in O(N) time.
Then, if there's a partially filled leaf level, then color those nodes red. The rest are black.
I am trying to get straight in my head how tree traversals can be used to uniquely identify a tree, and the crux of it seems to be whether the tree is a vanilla Binary Tree (BT), or if it also has the stricter stipulation of being a Binary Search Tree (BST). This article seems to indicate that for BT's, a single inorder, preorder and postorder traversal will not uniquely identify a tree (uniquely means structure and values of keys in this context). Here is a quick summary of the article:
BTs
1. We can uniquely reconstruct a BT with preorder + inorder and postorder + inorder.
2. We can also use preorder + postorder if we also stipulate that the traversals keeps track of the null children of a node.
(an open question (for me) is if the above is still true if the BT can have non-unique elements)
BSTs
3. We cannot use inorder for a unique id. We need inorder + preorder, or inorder + postorder.
Now, (finally) my question is, can we use just pre-order or just post-order to uniquely identify a BST? I think that we can, since this question and
answer
seems to say yes, we can use preorder, but any input much appreciated.
I can't tell what's being asked here. Any binary tree, whether it's ordered or not, can be serialized by writing out a sequence of operations needed to reconstruct the tree. Imagine a simple stack machine with just two instructions:
Push an empty tree (or NULL pointer if you like) onto the stack
Allocate a new internal node N, stuff a value into N, pop the top two trees off the stack and make them N's left and right children, and finally push N onto the stack.
Any binary tree can be serialized as a "program" for such a machine.
The serialization algorithm uses a postorder traversal.
Okay, you can use preorder only to identify a tree. This is possible because only in preorder traversal does the id-of-current-node comes before the ids of children. So you can read the traversal output root-to-leaves.
You can check http://en.wikipedia.org/wiki/Tree_traversal#Pre-order to confirm
So you can consider a preorder traversal as a list of insertions into a tree. Because the tree insertion into BST is deterministic, when you insert a list of values into an empty tree, you always get the same tree.
We are dealing with a Most similar neigthbour algorithm here. Part of the algorithm involves searching in order over a tree.
The thing is that until now, we cant make that tree to be binary.
Is there an analog to in order traversal for non binary trees. Particularly, I think there is, just traversing the nodes from left to right (and processing the parent node only once?")
Any thoughts?
update
This tree will have in each node a small graph of n objects. Each node will have n children (1 per each element in the graph), each of which will be another graph. So its "kind of" a b tree, without all the overflow - underflow mechanics. So I guess the most similar in order traversal would be similar to a btree inorder traversal ?
Thanks in advance.
Yes, but you need to define what the order is. Post and Pre order are identical, but inorder takes a definition of how the branches compare with the nodes.
There is no simple analog of the in-order sequence for trees other than binary trees (actually in-order is a way to get sorted elements from a binary search tree).
You can find more detail in "The art of computer programming" by Knuth, vol. 1, page 336.
If breadth-first search can serve your purpose then you can use that.
a BST(binary search tree) T is given.
how to find the nth smallest element of T ?
A binary search tree is effectively sorted, so you just need to go through the tree in-order and get to the nth spot. If the tree is fully balanced, you can calculate the spot to get to.
If the binary search tree is not fully balanced, then you need to do a recursive search to find the nth smallest element. This can be hugely accelerated by having each node store the number of subnodes pointed to by each of its branch pointers, effectively turning the search into a binary one. However, this add overhead on tree updates as each insertion or deletion now requires a leaf-to-root traversal to update the node counts.
Alternatively, you can keep the tree balanced, and use the above answer.
Is there any algorithm can traverse a tree recursively in level-first order and non-recursively in postorder.Thanks a lot.
To get an effectively recursive breadth-first search you can use iterative deepening depth-first search. It's particularly good for situations where the branching factor is high, where regular breadth-first search tends to choke from excessive memory consumption.
Edit: Marcos Marin already mentioned it, but for the sake of completeness, the Wikipedia page on breadth-first traversal describes the algorithm thus:
Enqueue the root node.
Dequeue a node and examine it.
If the element sought is found in this node, quit the search and return a result.
Otherwise enqueue any successors (the direct child nodes) that have not yet been discovered.
If the queue is empty, every node on the graph has been examined – quit the search and return "not found".
Repeat from Step 2.
Note: Using a stack instead of a queue would turn this algorithm into a depth-first search.
That last line is, obviously, interesting to you if you want to do a non-recursive depth-first traversal. Getting pre- or post-order is just a matter of modifying how you append the nodes in step 2.b.
You can recurse a tree in post order iteratively by using a stack instead of the implicit call stack used in recursion.
Wikipedia says,
Traversal
Compared to linear data structures
like linked lists and one dimensional
arrays, which have only one logical
means of traversal, tree structures
can be traversed in many different
ways. Starting at the root of a binary
tree, there are three main steps that
can be performed and the order in
which they are performed defines the
traversal type.
These steps (in no
particular order) are: performing an
action on the current node (referred
to as "visiting" the node), traversing
to the left child node, and traversing
to the right child node. Thus the
process is most easily described
through recursion.
To traverse a non-empty binary tree in
preorder, perform the following
operations recursively at each node,
starting with the root node:
Visit the node.
Traverse the left subtree.
Traverse the right subtree. (This is also called Depth-first
traversal.)
To traverse a non-empty binary tree in
inorder, perform the following
operations recursively at each node:
Traverse the left subtree.
Visit the node.
Traverse the right subtree. (This is also called Symmetric traversal.)
To traverse a non-empty binary tree in
postorder, perform the following
operations recursively at each node:
Traverse the left subtree.
Traverse the right subtree.
Visit the node.
Finally, trees can also be traversed
in level-order, where we visit every
node on a level before going to a
lower level. This is also called
Breadth-first traversal.