【问题标题】:Iterator on several sets多个集合上的迭代器
【发布时间】:2013-06-27 20:51:52
【问题描述】:

我正在写一个 Graph 类,

我保留一个HashMap,其中节点的 id(int 值)映射到关联的节点,并且我使用 adjacency list 方法来保持从节点开始的边(以 @987654323 的形式保持它们@)

请注意:此图是有向图且未加权的,

我想实现一个方法,该方法返回一个迭代器对类 Edge 的对象:

当在这个迭代器上获得下一个时,将获得一个 Edge 类的对象,该对象在它被遍历时立即创建,如果一个节点没有更多的邻居,它会转到下一个节点(顺序不重要)和如果没有更多的起始节点(所有都被遍历),它就结束了。

关于如何在边缘实现此迭代器而不事先将边缘保留在 Edge 类对象中的任何想法?

class Graph{
    HashMap<Integer , GraphNode> nodes;
    public Graph(){
        nodes = new HashMap<Integer ,GraphNode>();
    }
    public boolean addEdge(GraphNode n1 , GraphNode n2){
        if (!nodes.containsKey(n1) || !nodes.containsKey(n2))
            return false;
        return n1.addNeighbor(n2);
    }
    public boolean addNode(int id){
        if (nodes.containsKey(id))
            return false;
        nodes.put(id , new GraphNode(id));
        return true;
    }
    public boolean removeNode(GraphNode n1){
        if (!nodes.containsKey(n1.content))
            return false;
        for (GraphNode m : n1.neighbors)
            m.removeNeighbor(n1);
        nodes.remove(n1);
        return false;
    }
    public boolean removeEdge(GraphNode n1 , GraphNode n2){
        if (!nodes.containsKey(n1) || !nodes.containsKey(n2))
            return false;
        return n1.removeNeighbor(n2);
    }
    public Iterator<GraphNode> NodeIterator(){
        return nodes.values().iterator();
    }


   public Iterator<Edge> EdgeIterator(){
        Iterator<GraphNode> itr = this.NodeIterator();
        while (itr.hasNext){
            GraphNode n = itr.next();
            //......

        }
    }

}
class GraphNode{
    HashSet<GraphNode> neighbors;
    int content;
    public GraphNode(int content){
        this.content = content;
        neighbors = new HashSet<GraphNode>();
    }
    boolean addNeighbor(GraphNode n){
        if (neighbors.contains(n))
            return false;
        neighbors.add(n);
        return true;
    }
    boolean removeNeighbor(GraphNode n){
        if (!neighbors.contains(n))
            return false;
        neighbors.remove(n);
        return true;
    }


   }

class Edge{
    Node start , end;
    public Edge(Node start , Node end){
        this.start = start;
        this.end = end;
    }
}

【问题讨论】:

  • 你想实现什么?
  • 现在更新了,我要更新我解释的迭代器
  • 你要实现的图类型是什么?
  • 这是一个笼统的问题,我更想知道是否可以实现这样的迭代器,如果您向下滚动代码可以查看我要实现的方法

标签: java graph iterator


【解决方案1】:

我认为这样的事情可能会奏效:

public Iterator<Edge> EdgeIterator(){
    Iterator <Edge> edgeIter = new Iterator<Edge>() {

        private Iterator<GraphNode> itr = this.NodeIterator();
        private GraphNode currentNode;
        ... // additional private members as required

        public void remove()
        {
          // you don't have to implement this method if you don't need to support
          // this operation
        }

        public Edge next()
        {
          if (!hasNext())
            throw new NoSuchElementException ();

          return new Edge (x , y); // where you find x & y based on the current state 
                                   // of the iterator (kept in the private members of 
                                   // this instance)
        }

        public boolean hasNext()
        {
            return ?; // you return a boolean value based on the current state 
                      // of the iterator (kept in the private members of 
                      // this instance)
        }
    };

    return edgeIter;
}

EdgeIterator 方法创建一个Iterator&lt;Edge&gt; 并定义Iterator 接口的方法(我将这些方法的实现留给您)。 Iterator 实例包含一个 Iterator&lt;GraphNode&gt; 实例,用于迭代节点。

您应该向迭代器添加一些额外的私有成员,以跟踪当前节点(节点迭代器返回的最后一个节点)和您正在迭代的当前边。每当您完成对节点边缘的迭代时,您都会使用itr.next() 获得下一个节点(在检查是否有下一个节点可用之后)。边缘迭代器的next() 可以基于这些私有成员构造下一个Edge

【讨论】:

  • 你能看看我的代码吗?看看它是否正确
【解决方案2】:

正如 Eran 所说,我完成了迭代器方法的代码, 你觉得这个有用吗?

public Iterator<Edge> EdgeIterator(){
    Iterator<Edge> edgeIter = new Iterator<Edge>() {

        private Iterator<GraphNode> node_itr = NodeIterator();
        private Iterator<GraphNode> neighbor_itr;
        private GraphNode current_node;
        private GraphNode current_neighbor;
        public void remove()
        {
            if (current_node == null || current_neighbor == null)
                return;
            current_node.removeNeighbor(current_neighbor);
        }
        public Edge next()
        {
            if (neighbor_itr == null || !neighbor_itr.hasNext())
                if (node_itr.hasNext()){
                    current_node = node_itr.next();
                    neighbor_itr = current_node.neighbors.iterator();
                }else
                    return null;
            current_neighbor = neighbor_itr.next();
            return new Edge(current_node , current_neighbor);
        }
        public boolean hasNext()
        {
            if (neighbor_itr == null || !neighbor_itr.hasNext())
                if (node_itr.hasNext())
                    return node_itr.next().neighbors.iterator().hasNext();
                else
                    return false;
            return true;
        }
    };

    return edgeIter;
}

更新:编辑/工作版本:

public Iterator<Edge> EdgeIterator(){
    Iterator<Edge> edgeIter = new Iterator<Edge>() {
        private Iterator<GraphNode> node_itr = NodeIterator();
        private Iterator<GraphNode> neighbor_itr;
        private GraphNode current_node;
        private GraphNode current_neighbor;
        public void remove()
        {
            if (current_node == null || current_neighbor == null)
                return;
            current_node.removeNeighbor(current_neighbor);
        }
        private void moveNext(){
            if (neighbor_itr == null || !neighbor_itr.hasNext()){
                while (node_itr.hasNext()){
                    current_node = node_itr.next();
                    neighbor_itr = current_node.neighbors.iterator();
                    if (neighbor_itr.hasNext()){
                        break;
                    }
                }   
            }
        }
        public Edge next()
        {
            moveNext();
            current_neighbor = neighbor_itr.next();
            return new Edge(current_node , current_neighbor);
        }
        public boolean hasNext()
        {
            moveNext();
            return neighbor_itr.hasNext();
        }
    };

    return edgeIter;
}

【讨论】:

  • 您有几个错误: 1. 在hasNext() 中,您推进node_itr 而不存储结果,这意味着如果您调用hasNext() 后跟next(),您将跳过一个节点.为避免这种情况,hasNext() 应将node_iter.next() 的结果存储在current_node 中(在这种情况下还要初始化neighbor_itr)。 2. 在next()hasNext() 中,您不会处理迭代器返回的新节点没有邻居的情况(在这种情况下,您应该移动到下一个节点,直到找到有边的节点或到达最后一个节点)。
  • 是的,你是对的,实际上我更新了代码,但我不知道在哪里发布它,我添加了一个名为 moveNext() 的新方法,它移动到下一个至少有一个邻居(如果当前neighbor_itr 为空或没有next),但我不遍历邻居,在hasNext()next 的开头调用此方法跨度>
  • 为什么不编辑答案以显示代码的固定版本?我希望你的代码现在可以工作。
猜你喜欢
  • 2014-01-14
  • 2022-01-02
  • 2015-08-23
  • 1970-01-01
  • 2017-04-21
  • 1970-01-01
  • 1970-01-01
  • 2012-03-05
  • 1970-01-01
相关资源
最近更新 更多