Why is tree search considered to be costlier than graph search when a tree can never have a loop and can have only one parent node? Doesn't it mean you can never visit a node more than once if you don't have a loop?
Related
I'm having trouble conceptualising the process of deletion from a splay tree. Given this intial, tree, I want to delete the node 78.
Based on the information from my course (derived from Goodrich, Tamassia and Goldwasser), the deleted node in a BST should be replaced by the next node reached by performing an in-order traversal from the node which should be 91. This node should then be splayed to the top of the tree. However, this is not the case as shown on this visualiser here. https://www.cs.usfca.edu/~galles/visualization/SplayTree.html
The visualizer replaced 78 by its in order predecessor (70) instead and splayed that node. (The in order successor, i.e., the next key in sorted order is 83, not 91.) In general, splay trees are wonderfully malleable and as long as you approximately halve the length of the path you just descended while making every other path at most a little bit longer, you’re doing it right from an asymptotic performance standpoint (your professor may have different ideas, however).
Your textbook description:
the deleted node in a BST should be replaced by the next node reached by performing an in-order traversal from the node which should be 91
That description applies to unbalanced BST (binary search trees) but does not apply to most of the various kinds of balanced binary trees, and also does not apply to Splay Trees. To delete a node in a splay tree do the following:
Splay the node to be deleted to the root and dispose of it. This leaves two trees, call the left tree A and the right tree B.
The new root of the recombined tree will come from A. Splay the largest (rightmost) node of A tree to its root.
Because A's new root has the greatest key in A, it has no right child. Set the right child of A's new root to B.
A is the new combined tree.
This is what the visualization at https://www.cs.usfca.edu/%7Egalles/visualization/SplayTree.html did.
You said in comments to the other answer:
So in practice, the node that you choose to replace the deleted node doesn't really matter, i.e. affect performance etc.
In the typical splay tree deletion algorithm the node to replace will be the predecessor or successor node, in key order.
The rule of thumb is to always splay whenever a specific node is accessed. Find the node to delete, then splay it to the root. Find its predecessor, then splay it to the root. There are variations where you can splay less aggressively, too.
To search a certain node in AVL tree and balanced binary tree, it takes O(logn) time. Can I get the number of nodes which under this certain node in O(logn) time, too? If so, please elaborate. Pseudocode would be appreciate.
You need to keep a 'size' field in each nodes that keeps to size of the sub-tree that the nodes is it's root.
The implementation is that in each method of the tree you keep that field updated.
And the update is always: Father.size = SonA.size+SonB.size
Now the implementation itself is in every method of the tree, to call to the update method that I presented above in the relevant nodes.
Is there a way to search in a binary search tree starting from a node other than the root? E.g to start searching from a node in the third level of the tree.
Is there a way to search in a binary search tree starting from a node
other than the root?
Yes. There is.
But not with the traditional Binary Search Tree data structure.
You will have to modify the structure of a Node to achieve that.
One most straight forward way to achieve that is to have a pointer to root node from any other node. That way, you will be able to go to your root node directly from any given node and apply regular Binary Search algorithm. This method includes overhead of saving one more pointer to Root and would not change the time complexity of Binary Serach, it would remain O(lgN)
Other a bit complex way to achieve that would be to have a pointer to immidiate parent from any node. Given any node, you can first perform binary search on that subtree to find if the node to find exists on the subtree of the given node. That will finish the algorithm in O(lgM) where M is the number of nodes in the subtree. That search would be bit efficient because M < N. If you do not find the node in the subtree, then you will have to traverse back to the root. ( Root will have null as the parent pointer ) While traversing back, you can also track whether the node you are currently at is the node to find, if is is, you can directly return from there. Once you reach the root of the tree, you can apply standard Binary Serach algorithm. The time complexity for this method remains same as O(lgN). In most cases, the algorithm would finish faster than standard Binary Search.
I'm implementing a Digital Search Tree's 'delete' function.
What tree traversal algorithms should I use to find a leaf node that is a child of the deleted node?
The leaf not doesn't have to be the closest one or anything. Just a leaf.
Thank you
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.