Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Randomly select a node from a Binary Tree

My tree class:

public class BT<E>{
   E value;
   BT<E> left, right;

   public BT(E value)
   {
      this.value=value;
   }   

   public BT (E value, BT left, BT right) 
   {
      this.value = value;
      this.left = left;
      this.right = right;
   }

How would I go about returning a random node from a tree after I have generated a tree? I know the depth and the number of nodes for every tree I generate.

like image 519
RK2015 Avatar asked Aug 14 '15 13:08

RK2015


People also ask

How to choose root node in binary search tree?

Whenever an element is to be inserted, first locate its proper location. Start searching from the root node, then if the data is less than the key value, search for the empty location in the left subtree and insert the data. Otherwise, search for the empty location in the right subtree and insert the data.

What will be the probability of selecting a random node from a given single linked list?

Given a singly linked list, select a random node from the linked list (the probability of picking a node should be 1/N if there are N nodes in the list).

How do you select a node in a linked list?

Count the number of nodes by traversing the list. Traverse the list again and select every node with a probability of 1/N. The selection can be done by generating a random number from 0 to N-i for the node, and selecting the i'th node only if the generated number is equal to 0 (or any other fixed number from 0 to N-i).

How do you generate a random binary tree?

Devroye & Kruszewski (1996) generate random binary trees with n nodes by generating a real-valued random variable x in the unit interval (0,1), assigning the first xn nodes (rounded down to an integer number of nodes) to the left subtree, the next node to the root, and the remaining nodes to the right subtree, and ...


1 Answers

The algorithms from Dennis and Jeroen are simple to implement but O(n). I believe I have a O(log n) algorithm that is slightly more complicated.

Every node needs an equal chance of being selected. So at some tree T, let LN(T) be the number of nodes in the left tree, RN(T) be the number of nodes in the right tree, and N(T) be the number of total nodes, including this one (so N(T) = 1 + LN(T) + RN(T)). Select a random number R from 0 to N(T) - 1. If R == 0, return this node. If 1 <= R <= LT(N), recurse this method on the left subtree. Otherwise, recurse this method on the right subtree.

Untested code (assuming BT has a .size() method that works in O(1)):

public BT randomNode() {
    int r = new Random().nextInt(this.size());
    if (r == 0) {
        return this;
    } else if (left != null && 1 <= r && r <= left.size()) {
        return left.randomNode();
    } else {
        return right.randomNode();
    }
}

And of course you can do things like hoist the new Random() out of the method but the algorithm is the same.

Edit: fixed null pointer exception when left subtree was null.

like image 60
iobender Avatar answered Sep 17 '22 19:09

iobender