Returning an element with a specific rank k in a binary tree - binary-tree

I already implemented a method rankOfElement(x) in pseudocode which returns the rank for a given node x:
function rankofElement(x) {
rank = 0;
Node temp = root;
while (temp.key != x) {
if (x < temp.key) {
temp = temp.leftson
} else if (x > temp.key) {
rank += temp.leftson.size + 1;
temp = temp.rightson;
} else if (temp.key == x) {
return rank + temp.leftson.size
} else return "key not found"
}
Now I should implement a method (elementbyRank(k)) in pseudocode which returns a node with a specific rank k in the context of a binary tree.
I am struggling with that and I hope you can give me an answer.

So, if given rank k and we need to find a node with the given rank we first need a traversal algorithm to search through the tree. A pre-order traversal should work just fine. Here is a recursive one.
function preOrderTraversal(node){
if(node !== null){
print(node.data);
preOrderTraversal(node.left);
preOrderTraversal(node.right);
}
}
now that we have a way to get through our tree we need to implement the elementbyRank method and modify the traversal algorithm. Instead of printing the data we will check each node's rank. we will need to pass rank we need to find and we will need to add a return to the traversal.
The elementbyRank method is pretty simple:
function elementbyRank(k){
return preOrderTraversal(root, k);
}
Now we need to make the changes to the prePrderTraveral and let's change the name as well to elementbyRankTraversal.
function elementbyRankTraversal(node, key){
if(node !== null){
if(key == rankofElement(node.key))
return node;
return elementbyRankTraversal(node.left);
return elementbyRankTraversal(node.right);
}
return null;
}
So now if we find a node with the passed in rank, we will get that node back. but if one does not exist we will instead get a null value.
I know that you said given node x, the rankofElement(x) will return the rank of the element. but you are comparing the node's key directly to x which tell me that x is not a node but x is the key of node x. If I'm wrong then just remove the key part from elementbyRankTraversal().
And that should work.

Related

How to calculate a height of a tree

I am trying to learn DSA and got stuck on one problem.
How to calculate height of a tree. I mean normal tree, not any specific implementation of tree like BT or BST.
I have tried google but seems everyone is talking about Binary tree and nothing is available for normal tree.
Can anyone help me to redirect to some page or articles to calculate height of a tree.
Lets say a typical node in your tree is represented as Java class.
class Node{
Entry entry;
ArrayList<Node> children;
Node(Entry entry, ArrayList<Node> children){
this.entry = entry;
this.children = children;
}
ArrayList<Node> getChildren(){
return children;
}
}
Then a simple Height Function can be -
int getHeight(Node node){
if(node == null){
return 0;
}else if(node.getChildren() == null){
return 1;
} else{
int childrenMaxHeight = 0;
for(Node n : node.getChildren()){
childrenMaxHeight = Math.max(childrenMaxHeight, getHeight(n));
}
return 1 + childrenMaxHeight;
}
}
Then you just need to call this function passing the root of tree as argument. Since it traverse all the node exactly once, the run time is O(n).
1. If height of leaf node is considered as 0 / Or height is measured depending on number of edges in longest path from root to leaf :
int maxHeight(treeNode<int>* root){
if(root == NULL)
return -1; // -1 beacuse since a leaf node is 0 then NULL node should be -1
int h=0;
for(int i=0;i<root->childNodes.size();i++){
temp+=maxHeight(root->childNodes[i]);
if(temp>h){
h=temp;
}
}
return h+1;
}
2. If height of root node is considered 1:
int maxHeight(treeNode<int>* root){
if(root == NULL)
return 0;
int h=0;
for(int i=0;i<root->childNodes.size();i++){
temp+=maxHeight(root->childNodes[i]);
if(temp>h){
h=temp;
}
}
return h+1;
Above Code is based upon following class :
template <typename T>
class treeNode{
public:
T data;
vector<treeNode<T>*> childNodes; // vector for storing pointer to child treenode
creating Tree node
treeNode(T data){
this->data = data;
}
};
In case of 'normal tree' you can recursively calculate the height of tree in similar fashion to a binary tree but here you will have to consider all children at a node instead of just two.
To find a tree height a BFS iteration will work fine.
Edited form Wikipedia:
Breadth-First-Search(Graph, root):
create empty set S
create empty queues Q1, Q2
root.parent = NIL
height = -1
Q1.enqueue(root)
while Q1 is not empty:
height = height + 1
switch Q1 and Q2
while Q2 is not empty:
for each node n that is adjacent to current:
if n is not in S:
add n to S
n.parent = current
Q1.enqueue(n)
You can see that adding another queue allows me to know what level of the tree.
It iterates for each level, and for each mode in that level.
This is a discursion way to do it (opposite of recursive). So you don't have to worry about that too.
Run time is O(|V|+ |E|).

Computing rank of a node in a binary search tree

If each node in a binary search tree stores its weight (number of nodes in its subtree), what would be an efficient method to compute a rank of a given node (its index in the sorted list) as I search for it in the tree?
Start the rank at zero. As the binary search proceeds down from the root, add the sizes of all the left subtrees that the search skips by, including the left subtree of the found node.
I.e., when the search goes left (from parent to left child), it discovers no new values less than the searched item, so the rank stays the same. When it goes right, the parent plus all the nodes in the left subtree are less than the searched item, so add one plus the left subtree size. When it finds the searched item. any items in the left subtree of the node containing the item are less than it, so add this to the rank.
Putting this all together:
int rank_of(NODE *tree, int val) {
int rank = 0;
while (tree) {
if (val < tree->val) // move to left subtree
tree = tree->left;
else if (val > tree->val) {
rank += 1 + size(tree->left);
tree = tree->right;
}
else
return rank + size(tree->left);
}
return NOT_FOUND; // not found
}
This returns the zero-based rank. If you need 1-based then initialize rank to 1 instead of 0.
Since each node has a field storing its weight, the first you should implement a method call size() which return the number of nodes in a node's substree:
private int size(Node x)
{
if (x == null) return 0;
else return x.N;
}
then compute the rank of a given node is easy
public int rank(Node key)
{ return rank(key,root) }
private int rank(Node key,Node root)
{
if root == null
return 0;
int cmp = key.compareTo(root);
// key are smaller than root, then the rank in the whole tree
// is equal to the rank in the left subtree of the root.
if (cmp < 0) {
return rank(key, root.left)
}
//key are bigger than root,the the rank in the whole tree is equal
// to the size of subtree of the root plus 1 (the root) plus the rank
//in the right sub tree of the root.
else if(cmp > 0){
return size(root.left) + 1 + rank(key,root.right);
}
// key equals to the root, the rank is the size of left subtree of the root
else return size( root.left);
}
Depends on the BST implementation, but I believe you can solve it recursively.
public int rank(Key key){
return rank(root, key);
}
private int rank(Node n, Key key){
int count = 0;
if (n == null)return 0;
if (key.compareTo(n.key) > 0) count++;
return count + rank(n.left, key) + rank(n.right, key);
}

Find kth min node in AVL tree

I now have built a AVL tree, Here is a function to find kth min node in AVL tree
(k started from 0)
Code:
int kthMin(int k)
{
int input=k+1;
int count=0;
return KthElement(root,count,input);
}
int KthElement( IAVLTreeNode * root, int count, int k)
{
if( root)
{
KthElement(root->getLeft(), count,k);
count ++;
if( count == k)
return root->getKey();
KthElement(root->getRight(),count,k);
}
return NULL;
}
It can find some of right nodes, but some may fail, anyone can help me debug this>
THanks
From the root, after recursing left, count will be 1, regardless of how many nodes are on the left.
You need to change count in the recursive calls, so change count to be passed by reference (assuming this is C++).
int KthElement( IAVLTreeNode * root, int &count, int k)
(I don't think any other code changes are required to get pass by reference to work here).
And beyond that you need to actually return the value generated in the recursive call, i.e. change:
KthElement(root->getLeft(), count, k);
to:
int val = KthElement(root->getLeft(), count, k);
if (val != 0)
return val;
And similarly for getRight.
Note I used 0, not NULL. NULL is typically used to refer to a null pointer, and it converts to a 0 int (the latter is preferred when using int).
This of course assumes that 0 isn't a valid node in your tree (otherwise your code won't work). If it is, you'll need to find another value to use, or a pointer to the node instead (in which case you can use NULL to indicate not found).
Here is simple algorithm for Kth smallest node in any tree in general:-
count=0, found=false;
kthElement(Node p,int k) {
if(p==NULL)
return -1
else {
value = kthElement(p.left)
if(found)
return value
count++
if(count==k) {
found = true
return p.value
}
value = kthElement(p.right)
return value
}
}
Note:- Use of global variables is the key.

Is Doubly link list OR BST

Given a node with the following structure
class Node {
int data,
Node* P1,
Node* p2;
}
We need to determine, if the node represents a Circular Doubly Link List OR a Binary Tree.
In my opinion We need to start traversing the given node in one direction
node = givenNode;
while(node->P1 != null && node->P1 != givenNode)
{
node = node->p1
}
if(node == givenNode) // It means Circular DLL
else if(node == null) // It means Tree
And it would take O(n) time to detect this.
Please suggest if there is any better approach than this.
I suggest you could check if its a doubl-linked list or not with this piece of code:
node = givenNode;
if(givenNode->P1 == null || givenNode->P2 == null)
// It can not be double link list (circular)
else if(givenNode->p1->p2 == givenNode || givenNode->p2->p1 == givenNode)
{
//It is a double linked list
}
else
{
It is not a double linked list
}
And we have O(1) complexity

Binary Trees Count Number of Leaves

Suppose you already have the basic binary tree procedures isempty(bt), root(bt), left(bt), and right(bt). Write a procedure isLeaf(bt) that returns true if the binary tree bt is a leaf node and false if it is not.
This is what I have:
proc isLeaf(bt)
if (isEmpty(bt))
error('The binary tree is empty.');
elseif (left(bt) < right(bt))
return true;
else return false;
Then write a procedure numLeaves(bt) that returns the number of leaves in the binary tree bt.
This is what I have:
proc numLeaves(bt)
if (isEmpty(bt))
error ('The binary tree is empty.');
elseif (count left(bt) + right(bt));
return (left(bt) + right(bt);
please could you correct?
You'll learn very little to nothing if you don't try to solve this yourself, but just for people coming here looking for an answer:
boolean isLeaf (BinaryTree bt) {
return !isempty(bt) && isempty(left(bt)) && isempty(right(bt));
}
int numLeaves (BinaryTree bt) {
if (isempty(bt))
return 0;
else if (isLeaf(bt))
return 1;
else
return numLeaves(left(bt)) + numLeaves(right(bt));
}
The main idea here is to use recursion:
The number of leaves a node has is the sum of the number of leaves its left child has, and the number of leaves its right child has.
As #jeffrey greenham said that we can use recursion
int countleaves(struct node* root){
if(root!=null)
{
countleaves(root->left);
if(root->left==NULL&&root->right==NULL)
{
count++;
}
countleaves(root->right);
}
}

Resources