org.shaman.terrain.sketch.Graph.java Source code

Java tutorial

Introduction

Here is the source code for org.shaman.terrain.sketch.Graph.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package org.shaman.terrain.sketch;

import java.util.ArrayList;
import java.util.Iterator;
import org.apache.commons.lang3.tuple.*;

/**
 * A simple graph class for undirected, weighted graphs.
 *
 * @author Sebastian Weiss
 */
public class Graph implements Iterable<Triple<Integer, Integer, Float>> {

    private final ArrayList<ArrayList<MutablePair<Integer, Float>>> graph;

    public Graph() {
        this.graph = new ArrayList<>();
    }

    public int addNode() {
        int i = graph.size();
        graph.add(new ArrayList<MutablePair<Integer, Float>>());
        return i;
    }

    public void addEdge(int u, int v, float weight) {
        ArrayList<MutablePair<Integer, Float>> n1 = graph.get(u);
        ArrayList<MutablePair<Integer, Float>> n2 = graph.get(v);
        n1.add(new MutablePair<>(v, weight));
        n2.add(new MutablePair<>(u, weight));
    }

    public void setEdgeWeight(int u, int v, float weight) {
        ArrayList<MutablePair<Integer, Float>> n1 = graph.get(u);
        ArrayList<MutablePair<Integer, Float>> n2 = graph.get(v);
        for (MutablePair<Integer, Float> p : n1) {
            if (p.getLeft() == v) {
                p.setRight(weight);
                break;
            }
        }
        for (MutablePair<Integer, Float> p : n2) {
            if (p.getLeft() == u) {
                p.setRight(weight);
                break;
            }
        }
    }

    public void deleteEdge(int u, int v) {
        ArrayList<MutablePair<Integer, Float>> n1 = graph.get(u);
        ArrayList<MutablePair<Integer, Float>> n2 = graph.get(v);
        for (Iterator<MutablePair<Integer, Float>> it = n1.iterator(); it.hasNext();) {
            if (it.next().getLeft() == v) {
                it.remove();
                break;
            }
        }
        for (Iterator<MutablePair<Integer, Float>> it = n2.iterator(); it.hasNext();) {
            if (it.next().getLeft() == u) {
                it.remove();
                break;
            }
        }
    }

    @Override
    public Iterator<Triple<Integer, Integer, Float>> iterator() {
        return new Iterator<Triple<Integer, Integer, Float>>() {
            Triple<Integer, Integer, Float> current = null;
            private int u = 0;
            private int v = 0;

            @Override
            public boolean hasNext() {
                while (true) {
                    if (u == graph.size()) {
                        return false;
                    }
                    ArrayList<MutablePair<Integer, Float>> n = graph.get(u);
                    if (v == n.size()) {
                        v = 0;
                        u++;
                        continue;
                    }
                    MutablePair<Integer, Float> p = n.get(v);
                    v++;
                    if (p.getLeft() > u) {
                        current = new ImmutableTriple<>(u, p.getLeft(), p.getRight());
                        return true;
                    }
                }
            }

            @Override
            public Triple<Integer, Integer, Float> next() {
                return current;
            }

            @Override
            public void remove() {
                throw new UnsupportedOperationException("Not supported yet.");
            }
        };
    }

    // A recursive function that uses visited[] and parent to detect
    // cycle in subgraph reachable from vertex v.
    boolean isCyclicUtil(int v, boolean visited[], int parent) {
        // Mark the current node as visited
        visited[v] = true;

        // Recur for all the vertices adjacent to this vertex
        for (MutablePair<Integer, Float> p : graph.get(v)) {
            int i = p.getLeft();
            if (!visited[i]) {
                if (isCyclicUtil(i, visited, parent)) {
                    return true;
                } else if (i != parent) {
                    return true;
                }
            }
        }
        return false;
    }

    // Returns true if the graph contains a cycle, else false.
    boolean isCyclic() {
        // Mark all the vertices as not visited and not part of recursion
        // stack
        boolean[] visited = new boolean[graph.size()];

        // Call the recursive helper function to detect cycle in different
        // DFS trees
        for (int u = 0; u < graph.size(); u++) {
            if (!visited[u]) // Don't recur for u if it is already visited
            {
                if (isCyclicUtil(u, visited, -1)) {
                    return true;
                }
            }
        }

        return false;
    }
}