An extendable Graph datastructure. : Algorithms « Collections Data Structure « Java

Home
Java
1.2D Graphics GUI
2.3D
3.Advanced Graphics
4.Ant
5.Apache Common
6.Chart
7.Class
8.Collections Data Structure
9.Data Type
10.Database SQL JDBC
11.Design Pattern
12.Development Class
13.EJB3
14.Email
15.Event
16.File Input Output
17.Game
18.Generics
19.GWT
20.Hibernate
21.I18N
22.J2EE
23.J2ME
24.JDK 6
25.JNDI LDAP
26.JPA
27.JSP
28.JSTL
29.Language Basics
30.Network Protocol
31.PDF RTF
32.Reflection
33.Regular Expressions
34.Scripting
35.Security
36.Servlets
37.Spring
38.Swing Components
39.Swing JFC
40.SWT JFace Eclipse
41.Threads
42.Tiny Application
43.Velocity
44.Web Services SOA
45.XML
Java » Collections Data Structure » AlgorithmsScreenshots 
An extendable Graph datastructure.
       
// $Id: Graph.java 87 2010-04-09 02:12:11Z gabe.johnson@gmail.com $

//package org.six11.util.adt;

import java.util.List;
import java.util.Queue;
import java.util.Map;
import java.util.HashMap;
import java.util.ArrayList;

/**
 * An extendable Graph datastructure. This provides a starting point for a host of graph
 * datastructure applications, such as scheduling algorithms, decision trees, resource conflict
 * resolution, etc. It also may make you better looking.
 
 * The code here is a translation of the algorithms described in "Introduction to Algorithms" by
 * Cormen, Leiserson, and Rivest (aka "Big Red"). I've also added my own special sauce--callbacks (a
 * la Runnables) that you can use to follow the state of progress.
 **/
public class Graph {

  public final static int STATE_NONE = 0;
  public final static int STATE_BFS = 1;
  public final static int STATE_DFS = 2;

  public final static int WHITE = 0;
  public final static int GRAY = 1;
  public final static int BLACK = 2;

  public final static int UNKNOWN = 0;
  public final static int TREE = 1;
  public final static int BACK = 2;
  public final static int FORWARD = 3;
  public final static int CROSS = 4;

  // these contain all the nodes and edges
  protected List<Node> nodes;
  protected List<Edge> edges;

  // tells you if the graph edges are directed or undirected
  protected boolean directed;

  // search state indicates what the last search was, which tells you
  // what information you may be able to find out. a STATE_* value.
  transient protected int searchState = STATE_NONE;

  // if edgeDataValid is true, this tells you if the graph has ...
  transient protected boolean cycles;
  transient protected List<Edge> cross;
  transient protected boolean forward;
  transient protected boolean tree;

  // this tells us if the value of the above edge data vars can be
  // trusted. if not, we have to directly look at the set of nodes.
  transient protected boolean edgeDataValid;

  transient protected List<Node> startNodes;

  /**
   * Create a directed graph.
   */
  public Graph() {
    nodes = new ArrayList<Node>();
    edges = new ArrayList<Edge>();
    directed = true;
  }

  public void setDirected(boolean directed) {
    this.directed = directed;
  }

  public abstract static class NodeCallback {
    public abstract void run(Node n);
  }

  public static class Node {
    public Object data;

    private int state = WHITE;

    private int d = 0;
    private int f = 0;

    private Node p;
    private boolean child;

    // NodeCallbacks to invoke when entering a state.
    private Map<Integer, NodeCallback> actions;

    public Node(Object data) {
      this.data = data;
      this.actions = new HashMap<Integer, NodeCallback>();
    }

    protected boolean isVisited() {
      return state > WHITE;
    }

    protected void setState(int state) {
      if (this.state == state || state < WHITE || state > BLACK) {
        return;
      }
      this.state = state;
      // Debug.out("Graph", "Changed state of " + this + "#" + hashCode() + " to " + getStateStr());
      if (state == WHITE) {
        d = 0;
        f = 0;
        p = null;
        child = false;
      }
      if (actions.get(state!= null) {
        actions.get(state).run(Node.this);
      }
    }

    public int getState() {
      return state;
    }

    public String getStateStr() {
      String ret = "UNKNOWN";
      switch (state) {
        case WHITE:
          ret = "White";
          break;
        case GRAY:
          ret = "Gray";
          break;
        case BLACK:
          ret = "Black";
          break;
      }
      return ret;
    }

    public int getDistance() {
      return d;
    }

    public int getDiscovered() {
      return d;
    }

    public int getFinished() {
      return f;
    }

    protected void setDistance(int d) {
      this.d = d;
    }

    protected void setDiscovered(int t) {
      d = t;
    }

    protected void setFinished(int t) {
      f = t;
    }

    public Node getPredecessor() {
      return p;
    }

    protected void setPredecessor(Node p) {
      this.p = p;
      // Debug.out("Graph", "Changed parent of " + this + "#" + hashCode() + " to " + p);
    }

    protected void setChild() {
      child = true;
    }

    protected boolean isChild() {
      return child;
    }

    protected boolean isAncestor(Node a) {
      boolean ret = false;
      if (a != null && p != null) {
        ret = a.equals(p|| p.isAncestor(a);
      }
      return ret;
    }

    public void setAction(int state, NodeCallback cb) {
      actions.put(state, cb);
    }

    public boolean equals(Object other) {
      boolean ret = false;
      if (other instanceof Node) {
        Node n = (Nodeother;
        ret = data.equals(n.data);
      }
      return ret;
    }

    public String toString() {
      return (data == null super.toString() : data.toString());
    }
  }

  public abstract static class EdgeCallback {
    public abstract void run(Edge e);
  }

  public static class Edge {
    public Node a;
    public Node b;

    public Object data;
    private int mode;
    private Map<Integer, EdgeCallback> actions;

    public Edge(Node a, Node b, Object data) {
      this.a = a;
      this.b = b;
      this.data = data;
      actions = new HashMap<Integer, EdgeCallback>();
    }

    public void setAction(int state, EdgeCallback cb) {
      actions.put(state, cb);
    }

    public boolean equals(Object other) {
      boolean ret = false;
      if (other instanceof Edge) {
        Edge e = (Edgeother;
        ret = (a.equals(e.a&& b.equals(e.b&& data.equals(e.data));
      }
      return ret;
    }

    protected void setMode(int mode) {
      if (this.mode != mode) {
        this.mode = mode;
        if (actions.get(mode!= null) {
          actions.get(mode).run(Edge.this);
        }
      }
    }

    public int getMode() {
      return mode;
    }

    public String getModeStr() {
      String ret = "UNKNOWN";
      switch (mode) {
        case FORWARD:
          ret = "Forward";
          break;
        case TREE:
          ret = "Tree";
          break;
        case BACK:
          ret = "Back";
          break;
        case CROSS:
          ret = "Cross";
          break;

      }
      return ret;
    }

    public boolean isKnown() {
      return mode != UNKNOWN;
    }

    public boolean isTree() {
      return mode == TREE;
    }

    public boolean isBack() {
      return mode == BACK;
    }

    public boolean isForward() {
      return mode == FORWARD;
    }

    public boolean isCross() {
      return mode == CROSS;
    }

    public String toString() {
      String ns = a + "->" + b + " ";
      return (data == null ? ns + super.toString() : ns + data.toString());
    }
  }

  public void addNode(Node n) {
    if (!nodes.contains(n)) {
      nodes.add(n);
      clearState();
    }
  }

  public void removeNode(Node n) {
    if (nodes.contains(n)) {
      nodes.remove(n);
      clearState();
    }
  }

  /**
   * Tells you if this graph contains a node whose state and data are both equal (== or equals(..))
   * to the given Node.
   */
  public boolean containsNode(Node n) {
    return nodes.contains(n);
  }

  public boolean containsEdge(Edge e) {
    return edges.contains(e);
  }

  public boolean containsEdge(Node a, Node b) {
    boolean ret = false;
    for (Edge e : edges) {
      if (e.a.equals(a&& e.b.equals(b|| (!directed && e.b.equals(a&& e.a.equals(b))) {
        ret = true;
        break;
      }
    }
    return ret;
  }

  public void addEdge(Edge e) {
    if (!edges.contains(e)) {
      edges.add(e);
      clearState();
    }
  }

  public void removeEdge(Edge e) {
    if (edges.contains(e)) {
      edges.remove(e);
      clearState();
    }
  }

  protected void clearState() {
    searchState = STATE_NONE;
    edgeDataValid = false;
    startNodes = null;
  }

  public void bfs(Queue<Node> q) {
    clearState();
    for (Node n : nodes) {
      n.setState(q.contains(n? GRAY : WHITE);
    }
    for (Edge e : edges) {
      e.setMode(UNKNOWN);
    }
    for (Node n : q) {
      n.setDistance(0);
      n.setPredecessor(null);
    }
    while (!q.isEmpty()) {
      Node n = q.remove();
      List<Node> out = findNextNodes(n);
      for (Node m : out) {
        Edge e = findEdge(n, m);
        if (e != null) {
          if (m.getState() == WHITE) {
            e.setMode(TREE);
          else if (m.getState() == GRAY) {
            e.setMode(BACK);
          }
        }
        if (!m.isVisited()) {
          m.setDistance(n.getDistance() 1);
          m.setPredecessor(n);
          m.setState(GRAY);
          q.offer(m);
        }
      }
      n.setState(BLACK);
    }
    searchState = STATE_BFS;
  }

  public void dfs(List<Node> these) {
    clearState();
    for (Node n : nodes) {
      n.setState(WHITE);
      n.setPredecessor(null);
    }
    for (Edge e : edges) {
      e.setMode(UNKNOWN);
    }
    int time = 0;
    time = dfs(null, these, time);
    searchState = STATE_DFS;
  }

  public void dfs() {
    dfs(nodes);
  }

  protected int dfs(Node p, List<Node> out, int time) {
    for (Node n : out) {
      Edge e = findEdge(p, n);
      if (e != null) {
        n.setChild();
      }
      if (n.getState() == WHITE) {
        if (e != null) {
          e.setMode(1);
        }
        n.setPredecessor(p);
        time = dfsVisit(n, ++time);
      else if (p != null && n.getState() == GRAY && e != null) {
        e.setMode(2);
      else if (p != null && e != null) {
        if (n.isAncestor(p)) {
          e.setMode(3);
        else {
          e.setMode(4);
        }
      else if (e != null && e.getMode() == 0) {
        System.out.println(" --- ERROR  ---------");
        System.out.println(" - n.state: " + n.getState());
        System.out.println(" - e: " + e);
        System.out.println(" - p: " + p);
        System.out.println(" -------------------");
      }
    }
    return time;
  }

  protected int dfsVisit(Node n, int time) {
    n.setState(GRAY);
    n.setDiscovered(++time);
    List<Node> out = findNextNodes(n);
    dfs(n, out, time);
    n.setState(BLACK);
    n.setFinished(++time);
    return time;
  }

  public List<Node> findNextNodes(Node n) {
    List<Node> ret = new ArrayList<Node>();
    for (Edge e : edges) {
      if (e.a.equals(n)) {
        ret.add(e.b);
      }
      if (!directed && e.b.equals(n)) {
        ret.add(e.a);
      }
    }
    return ret;
  }

  public Edge findEdge(Node a, Node b) {
    Edge ret = null;
    if (a != null && b != null) {
      for (Edge e : edges) {
        if (e.a.equals(a&& e.b.equals(b)) {
          ret = e;
          break;
        else if (!directed && e.a.equals(b&& e.b.equals(a)) {
          ret = e;
          break;
        }
      }
    }
    return ret;
  }

  public List<Edge> findEdgesEntering(Node n) {
    List<Edge> ret = new ArrayList<Edge>();
    for (Edge e : edges) {
      if (e.b.equals(n)) {
        ret.add(e);
      }
    }
    return ret;
  }

  public List<Node> getNodes() {
    return nodes;
  }

  public List<Node> getNodes(Object data) {
    List<Node> ret = new ArrayList<Node>();
    for (Node n : nodes) {
      if (n.data.equals(data)) {
        ret.add(n);
      }
    }
    return ret;
  }

  public List<Edge> getEdges() {
    return edges;
  }

  public List<Edge> getCrossEdges() {
    computeEdgeData();
    return cross;
  }

  public List<Node> findStartNodes() {
    List<Node> ret;
    if (searchState != STATE_DFS) {
      dfs();
      ret = findStartNodes();
    else {
      if (startNodes == null) {
        startNodes = new ArrayList<Node>();
        for (Node n : nodes) {
          if (!n.isChild()) {
            startNodes.add(n);
          }
        }
      }
      ret = startNodes;
    }
    return ret;
  }

  public boolean hasCycles() {
    computeEdgeData();
    return cycles;
  }

  public boolean hasForward() {
    computeEdgeData();
    return forward;
  }

  public boolean hasCross() {
    computeEdgeData();
    return !cross.isEmpty();
  }

  public boolean hasTree() {
    computeEdgeData();
    return tree;
  }

  protected void computeEdgeData() {
    if (searchState != STATE_DFS) {
      dfs();
    }
    if (edgeDataValid)
      return;
    cycles = tree = forward = false;
    cross = new ArrayList<Edge>();
    for (Edge e : edges) {
      if (e.isBack()) {
        cycles = true;
      }
      if (e.isTree()) {
        tree = true;
      }
      if (e.isForward()) {
        forward = true;
      }
      if (e.isCross()) {
        cross.add(e);
      }
    }
    edgeDataValid = true;
  }
}

   
    
    
    
    
    
    
  
Related examples in the same category
1.AnagramsAnagrams
2.Hanoi puzzleHanoi puzzle
3.FibonacciFibonacci
4.Sieve Sieve
5.Find connections using a depth-first searchFind connections using a depth-first search
6.Find connections using hill climbing.
7.Find optimal solution using least-cost
8.Find the lost keysFind the lost keys
9.Compute the area of a triangle using Heron's FormulaCompute the area of a triangle using Heron's Formula
10.Compute prime numbers
11.Print a table of fahrenheit and celsius temperatures 1
12.Print a table of fahrenheit and celsius temperatures 2
13.Print a table of Fahrenheit and Celsius temperatures 3Print a table of Fahrenheit and Celsius temperatures 3
14.Soundex - the Soundex Algorithm, as described by KnuthSoundex - the Soundex Algorithm, as described by Knuth
15.A programmable Finite State Machine implementation.
16.Utilities for flop (floating-point operation) counting.
17.LU Decomposition
18.Reverse Polish Notation
19.Permutator test
20.implements the LZF lossless data compression algorithm
21.Linear Interpolation
22.Utility class for generating the k-subsets of the numbers 0 to n
23.VersionVersion
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.