Package bgu.bio.adt.graphs

Source Code of bgu.bio.adt.graphs.FlexibleGraph

package bgu.bio.adt.graphs;

import gnu.trove.list.array.TIntArrayList;

import java.util.ArrayList;

/**
* A class representing a flexible graph using array lists to hold the
* information (same functionality as {@link Graph})
*
* @author milon
*/
public class FlexibleGraph {
  /**
   * Holds the amount of nodes in the graph
   */
  protected int nodeNum;

  /**
   * Holds the amount of edges in a graph
   */
  protected int edgeNum;

  /**
   * Information on outgoing edges in the graph
   */
  public ArrayList<TIntArrayList> outAdjLists;

  /**
   * Information on the incoming edges in the graph
   */
  protected ArrayList<TIntArrayList> inAdjLists;

  /**
   * index the "in" neighborIx for an "out" neighbor.
   */
  protected ArrayList<TIntArrayList> inToOutNeighborIx;

  /**
   * Maximal out degree in the graph
   */
  protected int maxOutDeg;

  /**
   * Number of nodes with out degree of zero
   */
  protected int numOfLeaves;

  public FlexibleGraph() {
    this.outAdjLists = new ArrayList<TIntArrayList>();
    this.inAdjLists = new ArrayList<TIntArrayList>();
    this.inToOutNeighborIx = new ArrayList<TIntArrayList>();
    nodeNum = 0;
    edgeNum = 0;
    maxOutDeg = 0;
    numOfLeaves = 0;
  }

  /**
   * Add Node to the end of the list
   */
  /**
   * @return the id of the new node
   */
  public int addNode() {
    this.outAdjLists.add(new TIntArrayList());
    this.inAdjLists.add(new TIntArrayList());
    this.inToOutNeighborIx.add(new TIntArrayList());
    this.nodeNum = this.outAdjLists.size();
    this.numOfLeaves++;
    return this.nodeNum - 1;
  }

  /**
   * Add an edge to graph
   *
   * @param from
   *            the source of the edge
   * @param to
   *            the target of the edge
   */
  public void addEdge(int from, int to) {
    // if the previous size was zero then it is no longer a leaf
    if (this.outAdjLists.get(from).size() == 0) {
      this.numOfLeaves--;
    }
    this.outAdjLists.get(from).add(to);

    // check if the new edge turns the current node to the one with the
    // maximum degree
    if (this.maxOutDeg < this.outAdjLists.get(from).size()) {
      this.maxOutDeg = this.outAdjLists.get(from).size();
    }
    this.edgeNum++;

    // update the incoming edge information
    this.inAdjLists.get(to).add(from);
    this.inToOutNeighborIx.get(to).add(
        this.outAdjLists.get(from).size() - 1);
  }

  /**
   * Remove an edge from the graph
   *
   * @param from
   *            the source of the edge
   * @param to
   *            the target of the edge
   */
  public void removeEdge(int from, int to) {
    // if the size is one, then it is a new leaf
    final TIntArrayList fromOutList = this.outAdjLists.get(from);
    if (fromOutList.size() == 1) {
      this.numOfLeaves++;
      fromOutList.resetQuick();
    } else {
      int index = this.getNeighborIx(from, to);
      // switch the out edge in the list
      fromOutList.set(index, fromOutList.get(fromOutList.size() - 1));
      fromOutList.removeAt(index);

      // change the incoming edge index in the new node in the old
      // position
      final TIntArrayList toInList = this.inAdjLists.get(fromOutList
          .get(index));
      final TIntArrayList toInIndexList = this.inToOutNeighborIx
          .get(index);
      int foundPos = -1;
      for (int i = 0; i < toInList.size() && foundPos == -1; i++) {
        if (toInList.get(i) == from) {
          foundPos = i;
        }
      }
      toInIndexList.set(foundPos, index);
    }
    removeInEdge(from, to);
    edgeNum--;
    calcMaxOutDeg();
  }

  private void removeInEdge(int from, int to) {
    final TIntArrayList toInList = this.inAdjLists.get(to);
    final TIntArrayList toInIndexList = this.inToOutNeighborIx.get(to);
    if (inAdjLists.get(to).size() == 1) {
      toInList.resetQuick();
      toInIndexList.resetQuick();
    } else {
      int index = -1;
      for (int i = 0; i < toInList.size() && index == -1; i++) {
        if (toInList.get(i) == from) {
          index = i;
        }
      }
      // switch the locations
      toInList.set(index, toInList.get(toInList.size() - 1));
      toInIndexList.set(index,
          toInIndexList.get(toInIndexList.size() - 1));
      // remove the last location
      toInList.removeAt(toInList.size() - 1);
      toInIndexList.removeAt(toInIndexList.size() - 1);
    }
  }

  /**
   * Returns the number of nodes in the graph
   *
   * @return number of nodes in the graph
   */
  public int getNodeNum() {
    return nodeNum;
  }

  /**
   * Return the out degree of a node
   *
   * @param nodeIx
   *            the node ix
   * @return the number of adjacent nodes
   */
  public int outDeg(int nodeIx) {
    return outAdjLists.get(nodeIx).size();
  }

  /**
   * Return the in degree of a node
   *
   * @param nodeIx
   *            the node ix
   * @return the number of adjacent nodes
   */
  public int inDeg(int nodeIx) {
    return inAdjLists.get(nodeIx).size();
  }

  /**
   * Gets the neighbor given an index in the list.
   *
   * @param node
   *            the node index
   * @param neighborIx
   *            the neighbor index in the list
   * @return the neighbor id
   */
  public int getNeighbor(int node, int neighborIx) {
    return outAdjLists.get(node).get(neighborIx);
  }

  /**
   * Gets the neighbor index in the out adjacent list.
   *
   * @param node
   *            the node
   * @param neighbor
   *            the neighbor id
   * @return the neighbor index in the list of the node
   */
  public int getNeighborIx(int node, int neighbor) {
    final TIntArrayList is = outAdjLists.get(node);
    for (int ix = 0; ix < is.size(); ++ix) {
      if (is.get(ix) == neighbor) {
        return ix;
      }
    }
    return -1;
  }

  /**
   * Return the number of edges in the graph
   *
   * @return the number of the edges in the graph
   */
  public int getEdgeNum() {
    return this.edgeNum;
  }

  /**
   * Return the maximal out degree in the graph
   *
   * @return the maximal out degree in the graph
   */
  public int getMaxOutDeg() {
    return maxOutDeg;
  }

  /**
   * Return the number of nodes with out degree of zero
   *
   * @return the number of nodes with out degree of zero
   */
  public int getNumberOfLeaves() {
    return this.numOfLeaves;
  }

  private void calcMaxOutDeg() {
    this.maxOutDeg = -1;
    for (int i = 0; i < this.outAdjLists.size(); i++) {
      if (this.outAdjLists.get(i).size() > maxOutDeg) {
        maxOutDeg = this.outAdjLists.get(i).size();
      }
    }
  }

  /**
   * Return a representation of the graph in Graphviz format
   *
   * @return String representation of the graph in Graphviz format
   */
  public String toDOTFormat() {
    StringBuilder sb = new StringBuilder();
    sb.append("digraph graphname {\n");
    for (int i = 0; i < nodeNum; i++) {
      sb.append("n" + i + ";\n");
    }
    for (int i = 0; i < nodeNum; i++) {
      TIntArrayList outList = this.outAdjLists.get(i);
      for (int oInd = 0; oInd < outList.size(); oInd++) {
        sb.append("n" + i + " -> n" + outList.get(oInd) + ";\n");
      }
    }
    sb.append("}\n");
    return sb.toString();
  }
}
TOP

Related Classes of bgu.bio.adt.graphs.FlexibleGraph

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.