簡體   English   中英

Java:將節點添加到圖形錯誤

[英]Java: Adding nodes to graph bug

前言:我知道有高質量的圖形API。 我有興趣寫自己的自我完善。

這是我添加節點的功能:

    public void addNode(Vertex v, Collection<Edge> neighbors) {

        int originalSize = size();

        if (head == null) {
            head = v;
        }
        else {
            Collection<Edge> inEdges = new ArrayList<Edge>();
            inEdges.addAll(neighbors);

            traverseGraphToAdd(head, inEdges, v);
        }

        assert originalSize + 1 == size() : 
                        String.format("adding operation failed. original size: %d, current size: %d", originalSize, size());
    }
private void traverseGraphToAdd(Vertex start, Collection<Edge> inEdges, Vertex toAdd) {
        Iterator<Edge> iter = inEdges.iterator();
        Edge e;
        while (iter.hasNext()) {
            e = iter.next();
            if (e.getSource().equals(start)) {
                start.addEdge(e);
                iter.remove();
            }
            else if (! directionalEdges && e.getSink().equals(start)) {
                start.addEdge(e);
                iter.remove();
            }
        }
        if (inEdges.size() > 0) { //otherwise there's no point in continuing to search
            for (Edge arc : start.getOutEdges()) {
                traverseGraphToAdd(arc.getSink(), inEdges, toAdd);
            }
        }
    }

大小及其依賴性:

public int size() {
    int count = 0;
    if (head == null) {
        return 0;
    }
    else {
        count = countNodes(head);
    }
    clearVisited();
    return count;
}

private int countNodes(Vertex start) {
    int result = 1;
    start.setVisited(true);
    for (Edge e: start.getOutEdges()) {
        if (! e.getSink().isVisited()) {
            result += countNodes(e.getSink());
        }
    }
    return result;
}

private void clearVisited() {
    if (head != null) {
        clearNode(head);
    }
}

private void clearNode(Vertex start) {
    start.setVisited(false);
    for (Edge e: start.getOutEdges()) {
        if (e.getSink().isVisited()) {
            clearNode(e.getSink());
        }
    }
}

邊緣分類:

public Edge(Vertex source, Vertex sink, int weight) {
    this.source = source;
    this.sink = sink;
    this.weight = weight;
}

以下調用有效:

g.addNode(ftw, new HashSet<Edge>()); //first node - empty edges
g.addNode(odp, Arrays.asList(new Edge(ftw, odp, 3))); //link new node to one already in the graph

這不是:

g.addNode(tlt, Arrays.asList(new Edge(tlt, ftw, 2)));

在此示例中,Edge構造函數的第一個參數不是圖中已存在的節點。 我嘗試使用以下命令(從上面重復)在addNode中進行糾正:

if (e.getSource().equals(start)) { /*... */ }
else if (! directionalEdges && e.getSink().equals(start)) { /*... */ }

directionalEdges是一個類字段,它確定此圖是否是有方向的。

然而,這會導致的斷言錯誤:

Exception in thread "main" java.lang.AssertionError: adding operation failed. original size: 1, current size: 1

這里發生了什么?

您在示例中嘗試創建的圖形如下所示:

tlt -> ftw -> odp

創建后ftw -> odp ,你應該(和做的,我相信)有head == ftw 加入后tlt ,你應該有head == tlt如果你希望你的遍歷算法正常工作。 但是在您展示給我們的代碼中,只有一個地方分配了head ,並且僅在addNode()的第五行中head == null情況下才發生。 因此, head當您添加不改變tlt ,所以traverseGraphToAdd(),因此啟動形式ftw而不是tlt ,你打算為它。

但是,這里存在一個更普遍的問題,即您的代碼無法處理沒有根的有向圖(即,它們具有多個源節點)。請考慮如果您想要一個像這個:

a -> b <- c

我認為您會對此有疑問,因為您不再擁有一個頭腦。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM