Priority queues implemented with avl in python - insert

Operations insert, delete, search for an AVL tree are implemented. How can I
implement the operations insert, maximum, extract-max, increase-key, decrease-key that a priority queue should support in python?

An AVL tree is just a balanced binary search tree. The heap operations you've asked about can easily be implemented using the standard AVL operations.
insert - Just insert into the AVL tree as you normally would.
maximum - I assume you mean find-max. The maximum element in an AVL tree is the rightmost node. So just start at the root, traverse right pointers to the end, and return the leaf node.
extract-max - Find the maximum node as above, and delete it.
increase-key and decrease-key - Do a standard binary tree search to find the node you're interested in. Delete it from the tree. Modify the key. Re-insert into the tree.
Note that this won't be as efficient as a binary heap priority queue, but it will work.

Related

Best 'order' traversal to copy a balanced binary tree into an AVL tree with minimum rotations

I have two binary trees. One, A which I can access its nodes and pointers (left, right, parent) and B which I don't have access to any of its internals. The idea is to copy A into B by iterating over the nodes of A and doing an insert into B. B being an AVL tree, is there a traversal on A (preorder, inorder, postorder) so that there is a minimum number of rotations when inserting elements to B?
Edit:
The tree A is balanced, I just don't know the exact implementation;
Iteration on tree A needs to be done using only pointers (the programming language is C and there is no queue or stack data structure that I can make use of).
Rebalancing in AVL happens when the depth of one part of the tree exceeds the depth of some other part of the tree by more than one. So to avoid triggering a rebalance you want to feed nodes into the AVL tree one level at a time; that is, feed it all of the nodes from level N of the original tree before you feed it any of the nodes from level N+1.
That ordering would be achieved by a breadth-first traversal of the original tree.
Edit
OP added:
Iteration on tree A needs to be done using only pointers (the
programming language is C and there is no queue or stack data
structure that I can make use of).
That does not affect the answer to the question as posed, which is still that a breadth-first traversal requires the fewest rebalances.
It does affect the way you will implement the breadth-first traversal. If you can't use a predefined queue then there are several ways that you could implement your own queue in C: an array, if permitted, or some variety of linked list are the obvious choices.
If you aren't allowed to use dynamic memory allocation, and the size of the original tree is not bounded such that you can build a queue using a fixed buffer that is sized for the worst case, then you can abandon the queue-based approach and instead use recursion to visit successively deeper levels of the tree. (Imagine a recursive traversal that stops when it reaches a specified depth in the tree, and only emits a result for nodes at that specified depth. Wrap that recursion in a while or for loop that runs from a depth of zero to the maximum depth of the tree.)
If the original tree is not necessarily AVL-balanced, then you can't just copy it.
To ensure that there is no rebalancing in the new tree, you should create a complete binary tree, and you should insert the nodes in BFS/level order so that every intermediate tree is also complete.
A "complete" tree is one in which every level is full, except possibly the last. Since every complete tree is AVL-balanced, and every intermediate tree is complete, there will be no rebalancing required.
If you can't copy your original tree out into an array or other data structure, then you'll need to do log(N) in-order traversals of the original tree to copy all the nodes. During the first traversal, you select and copy the root. During the second, you select and copy level 2. During the third, you copy level 3, etc.
Whether or not a source node is selected for each level depends only on its index within the source tree, so the actual structure of the source tree is irrelevant.
Since each traversal takes O(N) time, the total time spent traversing is O(N log N). Since inserts take O(log N) time, though, that is how long insertion takes as well, so doing log N traversals does not increase the complexity of the overall process.

Level in binary tree with most nodes

What is the minimal amount of space needed to find out which level in binary tree (random or BST) has the most number of nodes?
If you are allowed to destroy the tree, then you can convert the tree to a linked list while doing a bfs of the tree, essentially simulating a queue with the tree itself!
You can find information about that here: Convert a binary tree to linked list, breadth first, constant storage/destructive
This requires only O(1) space as you have reused the nodes of the tree.
O(1)
Traverse the BT (Binary Tree) in Breadth-First-Search approach. Push nodes with mentioning the level of it. You will traverse all nodes in a level and then go to the next level. So just maintain the a maximum variable and keep updating it.
The Queue(for BST) could take space in O(2^(log(n) -1)).

Binary tree to Binary Search Tree (BST)

How can you convert Binary Tree to Binary Search Tree with O(1) extra space ?
Converting an unordered binary tree into an ordered binary search tree is trivial, but a bit more difficult to do fast.
Here's a naive implementation that should satisfy your criteria, I will not describe the actual steps to take, just the overall algorithm.
Grab a random leaf node from your existing tree
Unlink the leaf node from your existing tree
Make the node the root of your new binary search tree
Grab another random leaf node from your existing tree
Unlink that node from your existing tree
Find the right spot for, and link the node, into your new binary search tree
Repeat step 4-6 until the original tree is empty
You should require only a few variables, like the parent of the leaf node you're unlinking (unless the nodes has parent-links), the root node of the new tree, and a couple of temporary variables, all within your O(1) space criteria.
This will not produce an optimal binary search tree. For that you need to either sort the nodes before adding them, and adding them in the right order, or use a balancing binary search tree, like a red-black tree or a splay tree.
Convert Binary Tree to a doubly linked list- can be done inplace in O(n)
Then sort it using merge sort, nlogn
Convert the list back to a tree - O(n)
Simple nlogn solution.

Balanced Binary Tree

What is the name of the binary tree (or the family of the binary
trees), that is balanced, and has the minimum number of nodes
possible for its height?
balanced binary tree
(data structure)
Definition: A binary tree where no leaf is more than a certain amount farther from the root than any other. After inserting or deleting a node, the tree may rebalanced with "rotations."
Generalization (I am a kind of ...)
binary tree.
Specialization (... is a kind of me.)
AVL tree, red-black tree, B-tree, balanced binary search tree.
Aggregate child (... is a part of or used in me.)
left rotation, right rotation.
See also BB(α) tree, height-balanced tree.
-- http://www.itl.nist.gov/div897/sqg/dads/HTML/balancedbitr.html
It is called Fibonacci tree
AVL is a balanced tree with log(n) height (this is the lowest height possible for binary tree).
Another implementation of a similar data structure is Red Black Tree.
Both trees implement all operations in O(log(n)).
AVL Tree is something that you have been looking for.
From Wikipedia:
In computer science, an AVL tree is a self-balancing binary search tree, and it is the first such data structure to be invented. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; therefore, it is also said to be height-balanced. Lookup, insertion, and deletion all take O(log n) time in both the average and worst cases, where n is the number of nodes in the tree prior to the operation. Insertions and deletions may require the tree to be rebalanced by one or more tree rotations.

How can I efficiently get to the leaves of a binary-search tree?

I want to sum all the values in the leaves of a BST. Apparently, I can't get to the leaves without traversing the whole tree. Is this true? Can I get to the leaves without taking O(N) time?
You realize that the leaves themselves will be at least 1/2 of O(n) anyway?
There is no way to get the leaves of a tree without traversing the whole tree (especially if you want every single leaf), which will unfortunately operate in O(n) time. Are you sure that a tree is the best way to store your data if you want to access all of these leaves? There are other data structures which will allow more efficient access to your data.
To access all leaf nodes of a BST, you will have to traverse all the nodes of BST and that would be of order O(n).
One alternative is to use B+ tree where you can traverse to a leaf node in O(log n) time and after that all leaf nodes can be accessed sequentially to compute the sum. So, in your case it would be O(log n + k), where k is the number of leaf nodes and n is the total number of nodes in the B+ tree.
cheers
You will either have to traverse the tree searching for nodes without children, or modify the structure you are using to represent the tree to include a list of the leaf nodes. This will also necessitate modifying your insert and delete methods to maintain the list (for instance, if you remove the last child from a node, it becomes a leaf node). Unless the tree is very large, it's probably nice enough to just go ahead and traverse the tree.

Resources