从树中获取随机节点

时间:2016-07-14 20:55:40

标签: java binary-search-tree

我的方法是假设从BST返回一个随机节点,但它无法正常工作,我不确定为什么。假设该方法在递增计数器时使用前序遍历来遍历树。一旦计数器等于随机生成的数字,就会返回节点。

    // get random node
public Node getRandomNode(Node root) {

    // get random value between 0 to size of BST
    Random ran = new Random();
    int ranNum = ran.nextInt(size + 1);
    Node temp = root;
    System.out.println("random number is: " + ranNum);

    root = getRandomNode(ranNum, temp);
    return root;
}

int count = 0;

public Node getRandomNode(int ranNum, Node temp) {

    // traverse through the tree and increment count until count is the
    // random number,
    // in which case return the node it is on
    if (temp != null && count != ranNum) {
        count++;
        temp = getRandomNode(ranNum, temp.left);
        System.out.println(temp.data);
        temp = getRandomNode(ranNum, temp.right);

    }
    // if count is equal to the randomly generated number
    return temp;
}

编辑: 使用BFS

public Node getRandomNode(int ranNum, int count, Node temp) {

    if(temp == null)
        return null;

    Queue<Node> q = new LinkedList<Node>();
    q.add(temp);
    count++;    

    while(!q.isEmpty() && count != ranNum) {

        Node n = q.remove();
        System.out.println(" " + n.data);

        if(count == ranNum) {
            System.out.println("final node: " + n.data);
            return n;
        }

        if(n.left != null) {
            q.add(n.left);
            count++;
        }
        if(n.right != null) {
            q.add(n.right);
            count++;
        }
    }

    return temp;
}

2 个答案:

答案 0 :(得分:2)

您的问题出在递归调用中。假设随机数为1,您可能希望返回的结果是从左子树到达的第一个节点。你的代码会说temp = getRandomNode(ranNum, temp.left);,此时临时变量会保存正确的答案,然后你说temp = getRandomNode(ranNum, temp.right);,此时你的临时变量会有错误的答案。

编辑: 我决定尝试快速修复您的BFS实施(快速=未经测试)。请注意,我正在努力让我的代码尽可能地靠近你的代码,所以我避免对你的算法进行任何更改。

public Node getRandomNode(Node temp, int ranNum) {

    if(temp == null)
        return null;

    Queue<Node> q = new LinkedList<Node>();
    q.add(temp);
    int count = 0;

    while(!q.isEmpty() && count <= ranNum) {

        Node current = q.remove();
        System.out.println(" " + result.data);

        if(count == ranNum) {
            System.out.println("final node: " + n.data);
            return n;
        }

        if(n.left != null) {
            q.add(n.left);
        }
        if(n.right != null) {
            q.add(n.right);
        }
        count++
    }

    return null;
}

EDIT2: 决定修复你的其他版本(仍然试图非常接近你原来的设计)。

    // get random node
public Node getRandomNode(Node root) {

    // get random value between 0 to size of BST
    Random ran = new Random();
    int ranNum = ran.nextInt(size + 1);
    System.out.println("random number is: " + ranNum);

    return getRandomNode(ranNum, root);
}

int count = 0;

public Node getRandomNode(int ranNum, Node node) {

    // traverse through the tree and increment count until count is the
    // random number,
    // in which case return the node it is on
    if (node == null || count == ranNum) {
        return node;
    }
    count++;
    temp = getRandomNode(ranNum, temp.left);
    if (temp != null) {
        return temp;
    }
    return getRandomNode(ranNum, temp.right);
}

答案 1 :(得分:0)

您的实现并非完全随机,因为您正在根据计数(随机选取)检索随机节点,但不是随机遍历的! 当且仅当树为空时,树应该返回null。 因为你已经根据树的大小生成了随机数。

树有两条路径是向右还是向左......任何一条路都应该是随机的! 并且应该通过方法调用通过其中一个(除非分支已经用尽)。 我将count变量从field更改为方法参数&#39;因为它似乎是临时的,与class无关 因此,您不必重复每次使用课程的计数,这是一个很好的做法。 *另一个问题是你检查null如果一方有一个更少的话 数字比另一个使函数退出,因为节点是 如果这发生在左侧遍历它,则右边将替换临时值,但如果它发生在另一方面它可能返回null! 顺便认为这是伪代码我从来没有测试过它:)

public Node getRandomNode(Node root) {
 Random ran = new Random();
 int ranNum = ran.nextInt(size + 1);
 Node temp = root;
 System.out.println("random number is: " + ranNum);

 root = getRandomNode(ranNum, temp,0);
 return root;
}



public Node getRandomNode(int ranNum, Node temp, int count ) {

    // traverse through the tree and increment count until count is the
    // random number,
    // in which case return the node it is on
    if (temp != null && count != ranNum) {
        count++;
      Random pathRan = new Random();
      int pathNo= pathRan.nextInt(2);
      Node temp2 = null;
      if(pathNo == 0){//if 0 go to left
        temp2 = getRandomNode(ranNum, temp.left,count);
        if(temp2 == null){//this means that this path has nodes less than count ,so try the right.
           temp2 = getRandomNode(ranNum, temp.right,count);
        }


      }else{//go to right
        temp2 = getRandomNode(ranNum, temp.right,count);
         if(temp2 == null){//this means that this path has nodes less than count ,so try the left.
           temp2 = getRandomNode(ranNum, temp.left,count);
        }
      }
       return  temp2;
    }
    // if count is equal to the randomly generated number
    return temp;
}