我遇到了一个问题,那就是从主 node 获取所有sibling node ,并实现Java编写的进程n广度优先搜索算法.

我如何才能实现这一点?

我分享了我的代码片段,如下所示.

下面是我的Node类,如下所示.

public class Node{
    Node(int data){
       this.data = data;
       this.left = null;
       this.right = null;
       this.visited = false;
    }
    int data;
    Node left;
    Node right;
    boolean visited;

    // getter and setter 
}

下面是如下所示的初始化过程.

Node node1 = new Node(1);
Node node7 = new Node(7);
Node node9 = new Node(9);
Node node8 = new Node(8);
Node node2 = new Node(2);
Node node3 = new Node(3);
node1.left = node7;
node1.right = node9;
node7.right = node8;
node9.right = node3;
node9.left = node2;

下面是显示的方法.

public static void bfs(Node root){
        if (root == null){
            return;
        }
        
        Node temp; //a binary tree with a inner generic node class
        Queue<Node> queue = new LinkedList<>(); //can't instantiate a Queue since abstract, so use LLQueue
        
        queue.add(root);
        root.visited = true;
        while (!queue.isEmpty())
        {
            temp = queue.poll(); //remove the node from the queue
            
            // How can I get all siblings of the node like
            // for (Node sibling : temp.getSiblingNodes())
            // sibling.visited=true;
            // queue.add(sibling);
            
        }

        // get the result as a list
    }

推荐答案

因为Node有一个属性isVisited,所以我假设图中可能有循环.

该算法可以描述为以下步骤:

  • root node 标记为已访问并将其放入队列.

  • 然后重复,直到队列不为空:

    • 从队列头部移除 node (current个 node );
    • 判断其leftright个子 node .如果子 node 存在(即不是null)并且尚未被访问,则将该 node 同时添加到队列和sibling node 的结果列表中,并将子 node 的isVisited属性设置为true.

这就是它可能的实施方式:

public static List<Node> bfs(Node root) {
    if (root == null) return Collections.emptyList();
    
    List<Node> siblings = new ArrayList<>();
    Queue<Node> queue = new ArrayDeque<>(); // performs better than LinkedList
    
    queue.add(root);
    // siblings.add(root); // uncomment this line ONLY if you need the root-Node to be present in the result
    root.visited = true;
    
    while (!queue.isEmpty()) {
        Node current = queue.poll();

        tryAdd(siblings, queue, current.left);
        tryAdd(siblings, queue, current.right);
    }
    return siblings;
}

public static void tryAdd(List<Node> siblings, Queue<Node> queue, Node next) {
    if (next != null && !next.isVisited()) {
        queue.add(next);
        siblings.add(next);
        next.setVisited(true);
    }
}

为了避免对leftright个子 node 重复相同的操作,我创建了方法tryAdd().

我们可以通过引入Predicate(in this case condition is short and well readable, and this option is shown rather for education purposes)来改变其条件逻辑:

public static final Predicate<Node> IS_NULL_OR_VISITED =
    Predicate.<Node>isEqual(null).or(Node::isVisited);

public static void tryAdd(List<Node> siblings, Queue<Node> queue, Node next) {
    if (IS_NULL_OR_VISITED.test(next)) return;
    
    queue.add(next);
    siblings.add(next);
    next.setVisited(true);
}

Java相关问答推荐

无法运行Java(已解决)

Selenium Java:无法访问IFRAME内部的元素

那么比较似乎不是词典学的,尽管doctor 这么说

Android视图覆盖不阻止点击它后面的控件

CriteriaQuery with max

方法没有用正确的值填充数组—而是将数组保留为null,'

Android Studio—java—在onBindViewHolder中,将断点和空白添加到BackclerView中

neo4j java驱动程序是否会在错误发生时自动回滚事务?

使用Mockito进行的Junit测试失败

在Java中,在单个逻辑行中连接列表和单个元素的正确方法是什么?

无法了解Java线程所消耗的时间

在Java中如何从Executors.newFixedThreadPool(MAX_THREAD_COUNT())迁移到虚拟线程

将响应转换为带值的键

我如何解释这个错误?必需类型:供应商R,提供:收集器对象,捕获?,java.util.List java.lang.Object>>

SpringBoot:在条件{Variable}.isBlank/{Variable}.isEmpty不起作用的情况下进行路径变量验证

舰队运行配置Maven版本

基于配置switch 的@Controller的条件摄取

为什么mvn编译生命周期阶段不只是编译已更改的java文件?

如何修复Spring Boot应用程序中的RestDocumentationGenerationException:java.io.FileNotFoundException:/curl-request.adoc(只读文件系统)?

Swagger.io OpenApi v3.0 声明默认媒体类型