源码概览
1 、GraphDemo,用于演示一个图结构以及图的遍历。
2 、Graph,表示图数据结构,维护顶点的集合与边的集合,并提供广度优先遍历和深度优先遍历方法。
3 、Edge< V> ,表示图的一条边,维护了一条边相关的信息,如端点、边的权值、边的名称。泛型V表示权值的类型。
4 、GraphNode< V> ,表示图中的顶点,泛型V表示顶点存储的数据的类型;此类还维护了一个Boolean类型的变量isAccess,此变量用于在遍历时记录当前顶点是否被访问过,为true 表示访问过,false 表示未被访问过。
图的遍历
1 、深度优先遍历: 广度优先搜索:从图G的某个顶点v0出发,访问v0,然后选择一个与v0相邻且没被访问过的顶点vi访问,再从vi出发选择一个与vi相邻且未被访问的顶点vj进行访问,依次继续。如果当前被访问过的顶点的所 有邻接顶点都已被访问,则退回到已被访问的顶点序列中最后一个拥有未被访问的相邻顶点的顶点w, 从w出发按同样的方法向前遍历,直到图中所有顶点都被访问
2 、广度优先遍历:首先访问初始点vi,并将其标记为已访问过,接着访问vi的所有未被访问过的邻接点vi1, vi2, …, vi t,并均标记已访问过,然后再按照vi1, vi2, …, vi t的次序,访问每一个顶点的所有未被访问过的邻接点,并均标记为已访问过,依次类推,直到图中所有和初始点vi有路径相通的顶点都被访问过为止
源码如下():
package datastructure;
import java. util. Arrays;
public class GraphDemo {
public static void main ( String[ ] args) {
GraphNode< String> n1 = new GraphNode < > ( "v1" ) ;
GraphNode< String> n2 = new GraphNode < > ( "v2" ) ;
GraphNode< String> n3 = new GraphNode < > ( "v3" ) ;
GraphNode< String> n4 = new GraphNode < > ( "v4" ) ;
GraphNode< String> n5 = new GraphNode < > ( "v5" ) ;
Edge< Integer> e1 = new Edge < > ( 1 , "e1" , n1, n2) ;
Edge< Integer> e2 = new Edge < > ( 5 , "e2" , n2, n3) ;
Edge< Integer> e3 = new Edge < > ( 9 , "e3" , n1, n4) ;
Edge< Integer> e4 = new Edge < > ( 9 , "e4" , n3, n4) ;
Edge< Integer> e5 = new Edge < > ( 9 , "e5" , n2, n4) ;
Edge< Integer> e6 = new Edge < > ( 9 , "e6" , n1, n3) ;
Edge< Integer> e7 = new Edge < > ( 9 , "e7" , n4, n5) ;
Graph graph = new Graph ( ) ;
graph. addNode ( n1) ;
graph. addNode ( n2) ;
graph. addNode ( n3) ;
graph. addNode ( n4) ;
graph. addNode ( n5) ;
graph. addEdge ( e1) ;
graph. addEdge ( e2) ;
graph. addEdge ( e3) ;
graph. addEdge ( e4) ;
graph. addEdge ( e5) ;
graph. addEdge ( e6) ;
graph. addEdge ( e7) ;
GraphNode< ? > [ ] ns = { n1} ;
graph. wfsErgodic ( ns) ;
}
}
class Graph {
private GraphNode< ? > [ ] nodes;
private Edge< ? > [ ] edges;
private int n = 0 , e = 0 ;
public Graph ( ) {
this ( 18 , 9 ) ;
}
public Graph ( int nPoints, int nEdges) {
nodes = new GraphNode < ? > [ nPoints] ;
edges = new Edge < ? > [ nEdges] ;
}
public void addNode ( GraphNode< ? > node) {
try {
nodes[ n++ ] = node;
} catch ( ArrayIndexOutOfBoundsException e) {
pointArrayExpand ( ) ;
nodes[ n++ ] = node;
}
}
public void addEdge ( Edge< ? > edge) {
try {
edges[ e++ ] = edge;
} catch ( ArrayIndexOutOfBoundsException ex) {
edgeArrayExpand ( ) ;
edges[ e++ ] = edge;
}
}
private GraphNode< ? > [ ] getLinkedNodes ( GraphNode< ? > from) {
int count = 0 ;
for ( Edge< ? > e : edges) {
if ( e != null && e. getFrom ( ) == from) {
count++ ;
}
}
GraphNode< ? > [ ] linkedNodes = new GraphNode < ? > [ count] ;
int i = 0 ;
for ( Edge< ? > e : edges) {
if ( e != null && e. getFrom ( ) == from) {
GraphNode< ? > n = e. getTo ( ) ;
if ( n. isAccess) {
continue ;
}
linkedNodes[ i++ ] = n;
}
}
return linkedNodes;
}
private GraphNode< ? > [ ] getLinkedNodes ( GraphNode< ? > . . . nodes) {
int count = 0 ;
for ( GraphNode< ? > node : nodes) {
for ( Edge< ? > e : edges) {
if ( e != null && e. getFrom ( ) == node) {
count++ ;
}
}
}
GraphNode< ? > [ ] results = null;
int index = 0 ;
if ( count > 0 ) {
results = new GraphNode < ? > [ count] ;
for ( GraphNode< ? > node : nodes) {
for ( Edge< ? > e : edges) {
if ( e != null && e. getFrom ( ) == node) {
results[ index++ ] = e. getTo ( ) ;
}
}
}
}
return results;
}
public void wfsErgodic ( GraphNode< ? > . . . nodes) {
if ( nodes != null) {
for ( GraphNode< ? > n : nodes) {
if ( ! n. isAccess) {
System. out. println ( n. getData ( ) ) ;
n. isAccess = true ;
}
}
GraphNode< ? > [ ] linkedNodes = getLinkedNodes ( nodes) ;
wfsErgodic ( linkedNodes) ;
}
}
public void dfsErgodic ( GraphNode< ? > node) {
if ( node == null) {
return ;
}
if ( ! node. isAccess) {
System. out. println ( node. getData ( ) ) ;
node. isAccess = true ;
}
GraphNode< ? > [ ] graphNodes = getLinkedNodes ( node) ;
if ( Arrays. asList ( graphNodes) . isEmpty ( ) ) {
return ;
}
for ( int i = 0 ; i < graphNodes. length; i++ ) {
GraphNode< ? > v = graphNodes[ i] ;
dfsErgodic ( v) ;
}
}
private void pointArrayExpand ( ) {
if ( nodes. length < 64 ) {
nodes = Arrays. copyOf ( nodes, nodes. length * 2 ) ;
} else {
nodes = Arrays. copyOf ( nodes, ( int ) ( nodes. length * 1.5 ) ) ;
}
}
private void edgeArrayExpand ( ) {
if ( edges. length < 64 ) {
edges = Arrays. copyOf ( edges, ( int ) ( edges. length * 1.5 ) ) ;
} else {
edges = Arrays. copyOf ( edges, ( int ) ( edges. length * 1.2 ) ) ;
}
}
}
class Edge < V> {
private V weight;
private String name;
private GraphNode< ? > from, to;
public Edge ( ) {
}
public Edge ( V weight, String name, GraphNode< ? > from, GraphNode< ? > to) {
this . weight = weight;
this . name = name;
this . from = from;
this . to = to;
}
public V getWeight ( ) {
return weight;
}
public String getName ( ) {
return name;
}
public GraphNode< ? > getFrom ( ) {
return from;
}
public GraphNode< ? > getTo ( ) {
return to;
}
public void setWeight ( V weight) {
this . weight = weight;
}
public void setName ( String name) {
this . name = name;
}
public void setFrom ( GraphNode< ? > from) {
this . from = from;
}
public void setTo ( GraphNode< ? > to) {
this . to = to;
}
}
class GraphNode < V> {
private V data;
boolean isAccess = false ;
public GraphNode ( V data) {
this . data = data;
}
public V getData ( ) {
return data;
}
public void setData ( V data) {
this . data = data;
}
}