Open In App

Test Case Generation | Set 6 (Random Unweighted Binary Tree)

Generating Random Unweighted Binary Tree:



Approach: The problem can be solved using Queue. The idea is to traverse the tree using BFS. Follow the steps below to solve the problem:




// C++ Program to generate test cases for
// an unweighted tree
 
#include <bits/stdc++.h>
using namespace std;
 
 
// Function to generate the binary tree using BFS
vector<pair<int, int> > generateBinaryTree(int n)
{
     
     
    // Stores number of children
    // a node can have
    vector<int> options = { 0, 1, 2 };
     
     
    // Check if a node is already
    // included in the tree or not
    map<int, int> mp;
 
 
    // Stores node of tree at
    // each level of the tree
    queue<int> q;
 
 
    // Insert root node
    q.push(1);
 
 
    // Stores the generated tree
    vector<pair<int, int> > v;
 
 
    // Store count of nodes
    // already included
    int count = 1;
 
 
    // Marking the inclusion
    // of node 1
    mp[1] = 1;
 
 
    // Traverse tree using BFS
    while (!q.empty() or count < n) {
         
         
        // Stores from element
        // of queue
        int front;
         
        if(!q.empty()) {
             
             
            // Update front
            front = q.front();
             
             
            // Pop front element
            // of queue
            q.pop();
        }
         
         
         
 
 
        // Find count of child nodes
        // of current node
        int numberOfChilds
          = options[rand() % (options.size())];
 
 
        // If all the nodes are
        // already included
        if (count >= n)
            continue;
             
 
        // Connect child node to
        // the parent node
        while (numberOfChilds--) {
             
             
            // Stores value in node which
            // is not already included
            int child = rand() % n + 1;
 
 
            // Find the child until found a node
            // that is not yet included
            while (mp[child]) {
                child++;
                if (child > n) {
                    child = 1;
                }
            }
 
             
            // Update count
            count++;
 
 
            // Mark the included node
            mp[child] = 1;
 
 
            // Insert it to the generated tree
            // as {parent, child}
            v.push_back({ front, child });
 
 
            // Push the child into the queue
            q.push(child);
 
 
            // If all the nodes are included
            // break
            if (count == n)
                break;
        }
    }
 
 
    // Shuffle the v vector randomly
    random_shuffle(v.begin(), v.end());
 
    return v;
}
 
 
// Function to print the generated tree
void printTree(int n, vector<pair<int, int> > v)
{
    int s = v.size();
 
 
    // Number of nodes
    cout << n << "\n";
 
 
    // Print n-1 edges as {parent, child}
    for (int i = 0; i < v.size(); i++) {
        cout << v[i].first << " " << v[i].second << "\n";
    }
}
 
 
// Driver Code
int main()
{
     
     
    // Random seeding
    srand(time(NULL));
 
 
 
    // Number of node between 3 to 8
    // this range can be easily changed
    int n = rand() % 6 + 3;
 
 
    // Function Call
    vector<pair<int, int> > v
              = generateBinaryTree(n);
 
    // Print the generated tree
    printTree(n, v);
}




// Java Program for the above approach
 
import java.util.*;
 
public class Main {
 
    static List<Pair<Integer, Integer>> GenerateBinaryTree(int n) {
        Random rand = new Random();
        List<Integer> options = Arrays.asList(0, 1, 2);
        Map<Integer, Integer> mp = new HashMap<>();
        Queue<Integer> q = new LinkedList<>();
        List<Pair<Integer, Integer>> v = new ArrayList<>();
        int count = 1;
        q.offer(1);
        mp.put(1, 1);
        while (!q.isEmpty() || count < n) {
            int front = 0;
            if (!q.isEmpty()) {
                front = q.poll();
            }
            int numberOfChilds = options.get(rand.nextInt(options.size()));
            if (count >= n)
                continue;
            while (numberOfChilds-- > 0) {
                int child = rand.nextInt(n) + 1;
                while (mp.containsKey(child)) {
                    child++;
                    if (child > n) {
                        child = 1;
                    }
                }
                count++;
                mp.put(child, 1);
                v.add(new Pair<>(front, child));
                q.offer(child);
                if (count == n)
                    break;
            }
        }
        Collections.shuffle(v);
        return v;
    }
 
    static void PrintTree(int n, List<Pair<Integer, Integer>> v) {
        System.out.println(n);
        for (Pair<Integer, Integer> edge : v) {
            System.out.println(edge.getKey() + " " + edge.getValue());
        }
    }
 
    public static void main(String[] args) {
        Random rand = new Random();
        int n = rand.nextInt(7) + 3;
        List<Pair<Integer, Integer>> v = GenerateBinaryTree(n);
        PrintTree(n, v);
    }
 
    static class Pair<K, V> {
        private K key;
        private V value;
 
        public Pair(K key, V value) {
            this.key = key;
            this.value = value;
        }
 
        public K getKey() {
            return key;
        }
 
        public V getValue() {
            return value;
        }
    }
 
    public static class Extensions {
        public static <T> void shuffle(List<T> list) {
            Random rand = new Random();
            for (int i = list.size() - 1; i > 0; i--) {
                int j = rand.nextInt(i + 1);
                T temp = list.get(i);
                list.set(i, list.get(j));
                list.set(j, temp);
            }
        }
    }
}
 
// This code is contributed by Prince Kumar




#Python code for the above approach
import random
 
# Function to generate the binary tree using BFS
def generateBinaryTree(n):
     
    # Stores number of children
    # a node can have
    options = [0, 1, 2]
     
    # Check if a node is already
    # included in the tree or not
    mp = {}
 
    # Stores node of tree at
    # each level of the tree
    q = []
 
    # Insert root node
    q.append(1)
 
    # Stores the generated tree
    v = []
 
    # Store count of nodes
    # already included
    count = 1
 
    # Marking the inclusion
    # of node 1
    mp[1] = 1
 
    # Traverse tree using BFS
    while q or count < n:
         
        # Stores from element
        # of queue
        front = 0
         
        if q:
             
            # Update front
            front = q[0]
             
            # Pop front element
            # of queue
            q.pop(0)
         
        # Find count of child nodes
        # of current node
        numberOfChilds = options[random.randint(0, len(options)-1)]
 
        # If all the nodes are
        # already included
        if count >= n:
            continue
             
        # Connect child node to
        # the parent node
        while numberOfChilds:
             
            # Stores value in node which
            # is not already included
            child = random.randint(1, n)
 
            # Find the child until found a node
            # that is not yet included
            while child in mp:
                child += 1
                if child > n:
                    child = 1
 
            # Update count
            count += 1
 
            # Mark the included node
            mp[child] = 1
 
            # Insert it to the generated tree
            # as {parent, child}
            v.append((front, child))
 
            # Push the child into the queue
            q.append(child)
 
            # If all the nodes are included
            # break
            if count == n:
                break
            numberOfChilds -= 1
    # Shuffle the v list randomly
    random.shuffle(v)
 
    return v
 
# Function to print the generated tree
def printTree(n, v):
    # Number of nodes
    print(n)
 
    # Print n-1 edges as {parent, child}
    for i in range(len(v)):
        print(v[i][0], v[i][1])
 
# Driver Code
def main():
    # Random seeding
    random.seed()
 
    # Number of node between 3 to 8
    # this range can be easily changed
    n = random.randint(3, 8)
 
    # Function Call
    v = generateBinaryTree(n)
 
    # Print the generated tree
    printTree(n, v)
 
main()
 
# This code is contributed by Potta Lokesh




// C# program for the above approach
 
using System;
using System.Collections.Generic;
 
public class Program
{
    static List<(int, int)> GenerateBinaryTree(int n)
    {
        Random rand = new Random();
        var options = new List<int> { 0, 1, 2 };
        var mp = new Dictionary<int, int>();
        var q = new Queue<int>();
        var v = new List<(int, int)>();
        int count = 1;
        q.Enqueue(1);
        mp[1] = 1;
        while (q.Count > 0 || count < n)
        {
            int front = 0;
            if (q.Count > 0)
            {
                front = q.Dequeue();
            }
            int numberOfChilds = options[rand.Next(options.Count)];
            if (count >= n)
                continue;
            while (numberOfChilds-- > 0)
            {
                int child = rand.Next(1, n + 1);
                while (mp.ContainsKey(child))
                {
                    child++;
                    if (child > n)
                    {
                        child = 1;
                    }
                }
                count++;
                mp[child] = 1;
                v.Add((front, child));
                q.Enqueue(child);
                if (count == n)
                    break;
            }
        }
        v.Shuffle();
        return v;
    }
 
    static void PrintTree(int n, List<(int, int)> v)
    {
        Console.WriteLine(n);
        foreach (var edge in v)
        {
            Console.WriteLine($"{edge.Item1} {edge.Item2}");
        }
    }
 
    public static void Main()
    {
        Random rand = new Random();
        int n = rand.Next(3, 9);
        var v = GenerateBinaryTree(n);
        PrintTree(n, v);
    }
}
 
public static class Extensions
{
    public static void Shuffle<T>(this IList<T> list)
    {
        Random rand = new Random();
        for (int i = list.Count - 1; i > 0; i--)
        {
            int j = rand.Next(i + 1);
            T temp = list[i];
            list[i] = list[j];
            list[j] = temp;
        }
    }
}
 
// This code is contribute by princekumaras




// Function to generate the binary tree using BFS
function generateBinaryTree(n) {
  // Stores number of children
  // a node can have
  const options = [0, 1, 2];
 
  // Check if a node is already
  // included in the tree or not
  const mp = {};
 
  // Stores node of tree at
  // each level of the tree
  const q = [];
 
  // Insert root node
  q.push(1);
 
  // Stores the generated tree
  const v = [];
 
  // Store count of nodes
  // already included
  let count = 1;
 
  // Marking the inclusion
  // of node 1
  mp[1] = 1;
 
  // Traverse tree using BFS
  while (q.length || count < n) {
    // Stores from element
    // of queue
    let front = 0;
 
    if (q.length) {
      // Update front
      front = q[0];
 
      // Pop front element
      // of queue
      q.shift();
    }
 
    // Find count of child nodes
    // of current node
    let numberOfChilds = options[(Math.floor(Math.random() * options.length))];
 
    // If all the nodes are
    // already included
    if (count >= n) {
      continue;
    }
 
    // Connect child node to
    // the parent node
    while (numberOfChilds) {
      // Stores value in node which
      // is not already included
      let child = Math.floor(Math.random() * n) + 1;
 
      // Find the child until found a node
      // that is not yet included
      while (mp[child]) {
        child += 1;
        if (child > n) {
          child = 1;
        }
      }
 
      // Update count
      count += 1;
 
      // Mark the included node
      mp[child] = 1;
 
      // Insert it to the generated tree
      // as {parent, child}
      v.push([front, child]);
 
      // Push the child into the queue
      q.push(child);
 
      // If all the nodes are included
      // break
      if (count === n) {
        break;
      }
      numberOfChilds = numberOfChilds-1;
    }
  }
 
  // Shuffle the v list randomly
  shuffleArray(v);
 
  return v;
}
 
// Function to print the generated tree
function printTree(n, v) {
  // Number of nodes
  console.log(n);
 
  // Print n-1 edges as {parent, child}
  for (let i = 0; i < v.length; i++) {
    console.log(v[i][0], v[i][1]);
  }
}
 
// Helper function to shuffle array
function shuffleArray(array) {
  for (let i = array.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]];
  }
}
 
// Driver Code
function main() {
  // Random seeding
  Math.random();
 
  // Number of node between 3 to 8
  // this range can be easily changed
  const n = Math.floor(Math.random() * (8 - 3 + 1)) + 3;
 
  // Function Call
  const v = generateBinaryTree(n);
 
  // Print the generated tree
  printTree(n, v);
}
 
main();

Output:

5
5 4
1 2
1 3
3 5

Time Complexity : O(N log N)

Auxiliary Space : O(N)


Article Tags :