I have 2 questions regarding splay trees:
1. Deletion of a node
The book I am using says the following: ''When deleting a key k, we splay the parent of the node w that gets removed. Example deletion of 8:
However, what I am doing is this: If the deleted node is not the root, I splay it (to the root), delete it, and splay the right-most node of the left-subtree. But since in this case, the deleted node is the root, I simply remove it and splay the right-most node of the left subtree immediately. Like this:
Is this way also correct? Notice that it is totally different (like my root is 7 not 6 like my book says).
2. In which order are the values in a splay tree inserted?
Is it possible to ''get'' the order of the values that are inserted in the left tree example above? In other words, how is this tree made (in which order are the nodes inserted to generate the following tree). Is there a way to figure this out?
Re deleting a node: both algorithms are correct, and both take time O(log n) amortized. Splaying a node costs O(log n). Creating a new link near the root costs O(log n). Splay trees have a lot of flexibility in how they are accessed and restructured.
Re reconstructing the sequence of insertions: assuming that the insert method is the usual unbalanced insert and splay, then the root is the last insertion. Unfortunately, there are, in general, several ways that it could have been splayed to the root. An asymptotic improvement on the obvious O(n! poly(n))-time brute force algorithm is to do an exhaustive search with memoization, which has cost O(4^n poly(n)).
Related
I've been busting my head trying all kinds of ways but the best I got is O(log^2(n)).
the exact question is:
make a function Split(AVLtree T, int k) which returns 2 AVL trees (like a tuple) such that all values in T1 are lower than or equal to k and the rest are in T2. k is not necessarily in the tree. time must be O(log(n)).
Assume efficient implementation of AVL tree and I managed to make a merge function with time O(log(|h1-h2|)).
Any help would be greatly appriciated.
You're almost there, given that you have the merge function!
Do a regular successor search in the tree for k. This will trace out a path through the tree from the root to that successor node. Imagine cutting every edge traced out on the path this way, which will give you a collection of "pennants," single nodes with legal AVL trees hanging off to the sides. Then, show that if you merge them back together in the right order, the costs of the merges form a telescoping sum that adds up to O(log n).
Is it possible that we could perform m insert and delete operations on a balanced binary search tree such that delete operation deletes a node and the whole subtree below it and after that balance it? The whole process being in done in amortized O(log n) time per step?
Short answer: Yes it is possible.
What you are describing is a self balancing binary tree, like an AVL-tree or a Red-Black tree. Both take O(log n) for deletion, which includes reordering of the nodes. Here is a link to a page describing such trees and how they work in much more detail than I can, including illustrations. You can also check out the Wikipedia page of AVL-trees, they have a decent explanation as well as animations of the insertions. Here is a short version of what you were most interested in:
Deletions in an AVL tree are on average O(log n) and the rebalancing is on average O(log n), worst case O(1). This is done by doing rotations, again, well explained in both the sources.
The Wikipedia page also includes some code there, if you need to implement it.
EDIT:
For removing a subtree, you will still be able to do the same thing. Here is a link to a very good explanation of this. Short version: deleting the subtree is can be done O(log n) (keep in mind that deletion, regardless of the number of nodes deleted is still O(log n) as long as you do not directly rebalance the tree), then the tree would rebalance itself using rotations. This can also change the root of your tree. Removing a whole subtree is of course going to create a bigger height difference than just the deletion of one node at the end of the tree. Still, using rotation the tree can be rebalanced itself by finding the first node imbalance and then doing the AVL rebalancing scheme. Due to the use of the rotations, this should still all be O(log n). Here you will find how the tree rebalances itself after a deletion, which creates a height imbalance.
What I mean by general tree is an unbalanced tree with multiple child nodes (not restricted to 2 child node for each branch like Binary Tree). What is the Big-O complexity of remove node, insert node, find node
The average time complexity of searching in balanced BST in O(log(n)). The worst case complexity of searching in unbalanced binary tree is O(n).
If you're talking about a regular k-ary tree that does nothing special with its data, then to find any one node in the tree would take O(n) time assuming there are n nodes.
Inserting a node would be O(1) since you can store it wherever you want, and removing a node would be O(n) since you'd have to look at every node (worst case) to find the one to delete, and since there's no order to the data you don't have to do anything with the rest of the nodes.
I've been reading literature on AVL tree and found it is not elaborated very much on how many balance checks are needed in an AVL tree insertion / deletion.
For example, after inserting a node, do we need to check balance from the new node all the way up to the root? Or could we stop after a rotation(s) is committed?
How about in a deletion with the strategy of copying the rightmost node in the left sub-tree? Check up from the newly deleted (rightmost node in the left sub-tree) node to the root? could we stop after a rotation(s) is committed?
After an insertion, you need to update the balance factor of each "parent" all the way up the tree until the root; so it's a max of O(log n) updates. But you will only have to do a single restructuring to restore the tree to it's invariants.
After a delete, like insertion, you will have to update the balance factor all the way up the tree; so again it's O(log n) updates. But, unlike insert, you may have multiple restructuring rotations to restore the tree to it's invariants.
http://en.wikipedia.org/wiki/AVL_tree
I've been searching a bit deeper, and I've found when you can stop checking:
When the balance factor of an upper node of a node inserted is 0.
After a rotation. This is a consequence of the previous affirmation.
http://www.superstarcoders.com/blogs/posts/efficient-avl-tree-in-c-sharp.aspx
http://www.eternallyconfuzzled.com/tuts/datastructures/jsw_tut_avl.aspx
I've tried to understand what sorted trees are and binary trees and avl and and and ...
I'm still not sure, what makes a sorted tree sorted? And what is the complexity (Big-Oh) between searching in a sorted and searching in an unsorted tree? Hope you can help me.
Binary Trees
There exists two main types of binary trees, balanced and unbalanced. A balanced tree aims to keep the height of the tree (height = the amount of nodes between the root and the furthest child) as even as possible. There are several types of algorithms for balanced trees, the two most famous being AVL- and RedBlack-trees. The complexity for insert/delete/search operations on both AVL and RedBlack trees is O(log n) or better - which is the important part. Other self balancing algorithms are AA-, Splay- and Scapegoat-tree.
Balanced trees gain their property (and name) of being balanced from the fact that after every delete or insert operation on the tree the algorithm introspects the tree to make sure it's still balanced, if it's not it will try to fix this (which is done differently with each algorithm) by rotating nodes around in the tree.
Normal (or unbalanced) binary trees do not modify their structure to keep themselves balanced and have the risk of, most often overtime, to become very inefficient (especially if the values are inserted in order). However if performance is of no issue and you mainly want a sorted data structure then they might do. The complexity for insert/delete/search operations on an unbalanced tree range from O(1) (best case - if you want the root) to O(n) (worst-case if you inserted all nodes in order and want the largest node)
There exists another variation which is called a randomized binary tree which uses some kind of randomization to make sure the tree doesn't become fully unbalanced (which is the same as a linked list)
A binary search tree is an "tree"-structure where every node has two children-nodes.
The left nodes all have the property of being less than its parent, and the right-nodes are all greater than its parent.
The intressting thing with an binary-tree is that we can search for an value in O(log n) when the tree is properly sorted. Doing the same search in an LinkedList for an example would give us the searchspeed of O(n).
The best way to go about learning datastructures would be to do a day of googling and reading wikipedia articles.
This might get you started
http://en.wikipedia.org/wiki/Binary_search_tree
Do a google search for the following:
site:stackoverflow.com binary trees
to get a list of SO questions which will answer your several questions.
There isn't really a lot of point in using a tree structure if it isn't sorted in some fashion - if you are planning on searching for a node in the tree and it is unsorted, you will have to traverse the entire tree (O(n)). If you have a tree which is sorted in some fashion, then it is only necessary to traverse down a single branch of the tree (typically O(log n)).
In binary tree the right leaf is always smaller then the head, and the left leaf is always bigger, so you can search in sorted tree in O(log(n)), you just need to go right if if the key is smaller than head and to the left if bgger