/****************************************************************************
* ggraph.h :
* header file for GFC graph.
*
* Change Log :
* Aug 10, 1998 Initial version, Liujian Qian
*
* $Id: ggraph.h,v 1.14 1999/02/15 09:13:44 qian Exp $
***************************************************************************/
#ifndef _GADTGRAPH_H_
#define _GADTGRAPH_H_
#include <memory.h>
#include "gcxx.h"
#ifndef NOP
#define NOP
#endif
class ostream;
class GNode;
class GWire;
class GGraph;
//
// GUtilData.
// This is provided for defining various utility data
// associated with nodes/wires. The exact meaning of these
// utility data is up to the interpretation of the type
// of graphs and the algorithms of concern.
union GUtilData
{
GNode *n;
GWire *w;
GGraph *g;
char *s;
float f;
int i;
};
/**
* GNode represents a node (vertex) in the graph.
* All the nodes of a graph are linked together
* in a list. Each node points to a list of wires (arcs)
* of its own (which are all started from this node).
* The receiving node (end) of a wire is accessed by
* the wire's 'tip' field.
*
* Each node has a name and a (graph-wide) unique ID
* which is an integer.
*/
class GNode
{
friend class GGraph;
public:
GUtilData u,v,w, //util data used & interpreted by
x,y,z; //all sorts of graphs/algorithms
char name[64];
int id; //unique id in a graph
GNode *next; //next in the graph's node list
GWire *wire_list; //the wire list
public:
GNode();
/**
* just removes the wire from the node's wire_list.
* The wire object may still hang around in the memory.
*/
void removeWire(GWire* w);
/**
* custom memory allocator for graph nodes.
*/
//void * operator new(size_t);
/**
* custom memory deallocator for graph nodes.
*/
//void operator delete(void* ep, size_t);
};
/**
* GWire represents a wire (or edge, or arc) in the graph.
* Each wire has two integers representing its origin and
* destination node. It also points to the memory addr of receiving
* node (through the field 'tip')\. The data field w is used to
* store the weight (if any) on that wire. Default weight of a wire
* is 1.0.
*/
class GWire
{
friend class GGraph;
public:
GUtilData u,v,w; //util data provided for convenience
int orig, dest; //id for the two ends of the wire
GNode *tip; //where this wire points to.
GWire *next; //next wire with same origin (node)
GWire();
};
/**
* GGraph
* The general graph class. A graph has a list of nodes.
* Each node has its own list of wires that start from it.
*
* Many public methods have two versions, one based on the
* memory address of the nodes, one based on the id of the
* nodes. The second one is less efficient since a lookup based
* on the integer id is necessary. The advantage of id-based
* methods is that we can perform algorithms on disk-based
* (huge) graphs where the memory-address-based methods may
* fall short due to memory stress.
*
* (The structure of the GNode/GWire/GGraph is similar to those
* in The Stanford Graphbase, Knuth '94.)
*
*/
class GGraph
{
protected:
int n_nodes;
int n_wires;
GNode *node_list; //the global list of nodes
int next_node_id; //for auto-incremental ID. Never reused.
struct {
bool directed;
bool dynamic;
bool weighted_wire;
bool weighted_node;
}flags;
public:
NOP GGraph (bool _directed = false,
int _next_node_id = 0);
virtual ~GGraph ();
// node-related methods.
/**
* add a node to the graph. The node id is automatically
* assigned by the graph.
*/
virtual void addNode (GNode* nd);
/**
* same as above, except use the given node id.
*/
virtual void addNode (GNode* nd, int id);
/**
* delete a node (and all of related wires). The node
* object is completely vanished from the memory-space
* after this.
*/
virtual void delNode (GNode* nd);
/**
* same as above, provided for convenience.
*/
virtual void delNode (int id);
/**
* check if the given node is isolated or not connected to
* any other node.
*/
virtual bool isIsolated (int node_id);
virtual bool isIsolated (GNode* nd);
// wire-related methods.
/**
* establish connection between orig and dest. For undirected
* graph this actually adds two wires to the graph, one from
* orig->dest, another dest->orig. Weight is the weight to be
* assigned to the new wire(s).
* The new wire corresponding to the new connection is returned.
*/
virtual GWire* connect (GNode* orig, GNode* dest, float weight=1.0);
/**
* same as above, provided for convenience.
*/
virtual GWire* connect (int orig_id, int dest_id, float weight=1.0);
/**
* disconnect a pair of nodes. For undirected it deletes two
* wires from the graph.
*/
virtual void disconnect (GNode* orgi, GNode* dest);
virtual void disconnect (int orig_id, int dest_id);
// graph house-keeping methods
int numNodes () const {return n_nodes; }
int numWires () const {return n_wires; }
bool isDirected () const {return flags.directed; }
// completely wipes out all nodes
void freeNodes();
// completely wipe out all the wires.
void freeWires();
/**
* lookup and return the memory address of the
* node with the given id.
*/
GNode* lookup (int id) const;
/**
* check wether a node is a root node. This is only meaningful
* for directed graphs.
* A root node is not the 'tip' or destination of any wires in
* the graph.
*/
bool isRoot (GNode* nd) const;
bool isRoot (int id) const;
/**
* check if a node is a leaf node. This is only meaningful
* for directed graphs.
* A leaf node is a node that has no out-going wires.
*/
bool isLeaf (GNode* nd) const;
bool isLeaf (int id) const;
/**
* check wether two nodes are neighbor.
* Neighboring nodes have a direct wire between them.
*/
bool isNeighbor (GNode* nd1, GNode* nd2);
bool isNeighbor (int id1, int id2);
/**
* check wether two nodes are connected. Two nodes are
* connected if they are either 1) neighbors, or 2)
* there exists a path from nd1--->nd2. For digraph
* nd1 must be the origin node, and nd2 the destination
* node for the path.
*/
bool isConnected (GNode* nd1, GNode* nd2);
bool isConnected (int id1, int id2);
/**
* calculate the diameter of the graph.
* The diameter of a graph is the longest path from
* one node to another.
*/
int diameter ();
//////////////////////////////////////////////////
// Graph Algorithms
/**
* find out the shortest path from orig to dest.
* A linked list of nodes on the desired path, starting
* with 'orig', is returned when successful. The utility
* data field GNode::z is used to link all the nodes on
* the path together. Also note that the weight is stored
* in each wire's GWire::w.f field.
*/
GNode* shortestPath (GNode* orig, GNode* dest);
GNode* shortestPath (int orig_id, int dest_id);
/**
* check whether the graph is a planar one.
*/
bool isPlanar () const;
friend
ostream& operator<<(ostream& os, const GGraph& g);
protected:
//stuff that does the dirty work
GWire* _connect1 (GNode* orig, GNode* dest, float weight);
void _disconnect1 (GNode* orig, GNode* dest);
};
#endif
Documentation generated by lqian@lqian-sun on Wed Jul 14 09:36:10 EDT 1999