I have an AVL tree with n nodes, where they are sorted by index 1,2,3,4...,n
I want to increase the index of all nodes in [i,j] by d, how can I do this in O(log n)?
For example:
I my tree had 1,2,3,4 and d=3 and I got [2,4] then the new AVL tree will hold 1,5,6,7
Related
Assume the following notation/operations on AVL trees. An empty AVL tree is denoted E. A
non-empty AVL tree T has three attributes:
• The key T.key is the root node’s key.
• The left child T.left is T’s left subtree, which is an AVL tree (possibly E).
• The right child T.right is T’s right subtree, which is an AVL tree (possibly E).
I'm trying to write an algorithm (pseudocode would do) Count(T, lo, hi) that counts and returns the number of nodes in an AVL tree with root T, where the key value is in the range lo ≤ key ≤ hi. I want it to have time complexity O(n) where n is the number of nodes in the AVL tree T. One idea I had was recursion but this didn't seem to have the required complexity. Any ideas?
You can add a global variable like counter, iterate the tree with Pre-order this has a cost of (n+e) and add 1 for each node.
You can add a counter too, and when add a new node inside the data structure, you can add 1, and if you remove a node you can subtract 1
The problem statement is as follows:
Imagine you are reading in a stream of integers. Periodically, you
wish to be able to look up the rank of a number x (the number of
values less than or equal to x). Implement the data structures and
algorithms to support these operations.That is, implement the method
track (in t x), which is called when each number is generated, and the
method getRankOfNumber(int x) , which returns the number of values
less than or equal to X (not including x itself).
EXAMPLE: Stream(in order of appearance): 5, 1, 4, 4, 5, 9, 7, 13, 3
getRankOfNumber(1) = 0 getRankOfNumber(3) = 1 getRankOfNumber(4) = 3
The suggested solution uses a modified Binary Search Tree, where each node stores stores the number of nodes to the left of that node. The time complexity for both methods is is O(logN) for balanced tree and O(N) for unbalanced tree, where N is the number of nodes.
But how can we construct a balanced BST from a stream of random integers? Won't the tree become unbalanced in due time if we keep on adding to the same tree and the root is not the median? Shouldn't the worst case complexity be O(N) for this solution (in which case a HashMap with O(1) and O(N) for track() and getRankOfNumber() respectively would be better)?
you just need to build an AVL or Red-Black Tree to have the O(lg n) complexities you desire.
about the rank, its kind of simple. Let's call count(T) the number of elements of a tree with root T.
the rank of a node N will be:
firstly there will be count(N's left subtree) nodes before N (elements smaller than N)
let A = N's father. If N is right son of A, then there will be 1 + count(A's left subtree) nodes before N
if A is right son of some B, then there will be 1 + count(B's left subtree) nodes before N
recursively, run all the way up until you reach the root or until the node you are in isn't someone's right son.
as the height of a balanced tree is at most lg(n), this method will take O(lg n) to return you someone's rank ( O(lg n) to find + O(lg n) to run back and measure the rank ), but this taking in consideration that all nodes store the sizes of their left and right subtrees.
hope that helps :)
Building a Binary Search Tree (BST) using the stream of numbers should be easier to imagine. All the values less than the node, goes to the left and all the values greater than the node, goes to the right.
Then Rank of any x will be number of nodes in left subtree of that node with value x.
Operations to be done: Find the node with Value x O(logN) + Count Nodes of left Subtree of node found O(logN) = Total O(logN + logN) = O(logN)
In case to optimize searching of counts of node of left subtree from O(logN) to O(1), you can keep another class variable 'leftSubTreeSize' in Node class, and populate it during insertion of a node.
Is there an algorithm that with a given 2-3 tree T and a pointer to some node v in said tree, the algo can change the key of the node v so T would remain a legal 2-3 tree, in O(logn/loglogn) amortized efficiency?
No.
Assume it was possible, with the algorithm f, we will show we can sort an array with O(n*logn/loglogn) time complexity.
sort array A of length n:
(1) Create an 2-3 tree of size n, with no importance to keys. let it be T.
(2) store all pointers to nodes in T in a second array B.
(3) for each i from 0 to n:
(3.1) f(B[i],A[i]) //modify the tree: pointer: B[i] new value: A[i]
(4) extract elements from T back to A inorder.
correctness:
After each activation of f the tree is legal. After finishing activating f on all elements of T and all elements of A, the tree is legal and contains all elements. Thus, extracting elements from A, we get back the sorted array.
complexity:
(1)Creating a tree [no importance which keys we put] is O(n) we can put 0 in all elements, it doesn't matter
(2)iterating T and creating B is O(n)
(3)activating f is O(logn/loglogn), thus invoking it n times is O(n*logn/loglogn)
(4) extracting elements is just a traversal: O(n)
Thus: total complexity is O(n*logn/loglogn)
But sorting is an Omega(nlogn) problem with comparisons based algorithms. contradiction.
Conclusion: desired f doesn't exist.
I saw this in some paper and someone argued that there can be at most log(n) times rotation when we delete a node of an AVL tree. I believe we can achieve this by generating an AVL tree as lopsided as possible. The problem is how to do this. This will help me a lot about researching the removal rotation thing. Thanks very much!
If you want to make a maximally lopsided AVL tree, you are looking for a Fibonacci tree, which is defined inductively as follows:
A Fibonacci tree of order 0 is empty.
A Fibonacci tree of order 1 is a single node.
A Fibonacci tree of order n + 2 is a node whose left child is a Fibonacci tree of order n and whose right child is a Fibonacci tree of order n + 1.
For example, here's a Fibonacci tree of order 5:
The Fibonacci trees represent the maximum amount of skew that an AVL tree can have, since if the balance factor were any more lopsided the balance factor of each node would exceed the limits placed by AVL trees.
You can use this definition to very easily generate maximally lopsided AVL trees:
function FibonacciTree(int order) {
if order = 0, return the empty tree.
if order = 1, create a single node and return it.
otherwise:
let left = FibonacciTree(order - 2)
let right = FibonacciTree(order - 1)
return a tree whose left child is "left" and whose right child is "right."
Hope this helps!
I'm currently implementing a red-black tree data structure to perform some optimizations for an application.
In my application, at a given point I need to remove all elements less than or equal to a given value (you can assume that the elements are integers) from the tree.
I could delete the elements one by one, but I would like to have something faster. Therefore, my question is: if I delete a whole subtree of a red-black tree, how could I fix the tree to recover the height and color invariants?
When you delete one element from a red-black tree it takes O(log n) time, where n is the number of elements currently in the tree.
If you remove only few of the elements, then it's best just to remove them one by one, ending up with O(k log n) operations (k = removed elements, n = elements in the tree before removals).
But if you know that you are going to remove a large number of nodes (e.g. 50% or more of the tree), then it's better to iterate through the elements you want to keep (O(k') operation where k' = elements what will be kept), then scrap the tree (O(1) or O(n) depending on your memory management scheme) and rebuild the tree (O(k' log k')) operation. The total complexity is O(k')+O(k' log k') = O(k' log k'), which obviously is less than O(k log n) when k' < k (you keep less than 50% of the tree).
Well, the point being anyway that when you are going to remove MOST of the elements, it's better in practice to enumerate the ones you want to keep and then rebuild the tree.
EDIT: The below is for a generic sub-tree delete. What you need is just a single Split operation (based on your actual question contents).
It is possible to delete a whole subtree of a Red-Black tree in worst case O(log n) time.
It is known that Split and Join operations on a red-black tree can be done in O(log n) time.
Split : Given a value k and a red-black Tree T, Split T into two red-black trees T1 and T2 such that all values in T1 < k and all values in T2 >= k.
Join : Combine two red-black trees T1 and T2 into a single red-black tree T. T1 and T2 satisfy max in T1 <= min in T2 (or T1 <= T2 in short).
What you need is two Splits and one Join.
In your case, the subtree you need to delete will correspond to a range of values L <= v <= U.
So you first Split on L, to get T1 and T2 with T1 <= T2. Split T2 on U to get T3 and T4 with T3 <= T4. Now Join the trees T1 and T4.
In pseudoCode, your code will look something like this:
Tree DeleteSubTree( Tree tree, Tree subTree) {
Key L = subTree.Min();
Key U = subTree.Max();
Pair <Tree> splitOnL = tree.Split(L);
Pair <Tree> splitOnU = splitOnL.Right.Split(U);
Tree newTree = splitOnL.Left.Join(splitOnU.Right);
return newTree;
}
See this for more information: https://cstheory.stackexchange.com/questions/1045/subrange-of-a-red-and-black-tree
Bulk deletion from a red-black tree is hard because the black-height invariant gets messed up pretty badly. Assuming you're not doing (soft) real-time, I would either delete one-by-one (since you had to insert them one by one, we're talking about a smaller constant factor here) or switch to a splay tree.