图的广度优先遍历:从一个结点出发,优先遍历与之相连的结点,然后再广度遍历第一个与该结点相连的结点,直到遍历完所有相连的结点。
需要考虑的情况:
- 因为结点之间是多对多的关系,所以有可能访问过的结点会再次被访问,因此需要标识已经访问过的结点;
- 图有可能是非连通图,所以从一个结点出发并不能访问所有结点,因此需要加一个循环来判断是否所有结点已被访问;
不难从图中观察到,结点的遍历是有先进先出的特点,所以选用队列来进行存储结点。
广度优先遍历代码:
/**
*
*********************
* @Title: breadthFirstTraverse
* @Description: TODO(To travel the graph with breadth first.)
*
*********************
*
*/
public String breadthFirstTraverse(int paraStartNode) {
String resultString = "";
int numberNodes = connectivityMatrix.getData().length;
initVisited(numberNodes);
resultString = breadthFirstVisit(paraStartNode, resultString, numberNodes);
for (int i = 0; i < numberNodes; i++) {
if (!visited[i]) {
resultString = breadthFirstVisit(i, resultString, numberNodes);
} // Of if
} // Of for i
return resultString;
}// Of breadthFirstTraverse
/**
*
*********************
* @Title: breadthFirstVisit
* @Description: TODO(To traverse the connected subgraph.)
*
* @param paraNode The start node.
* @param paraString The result.
* @param paraNumberNode The number of nodes.
*********************
*
*/
public String breadthFirstVisit(int paraNode, String paraString, int paraNumberNode) {
CircleObjectQueue tempQueue = new CircleObjectQueue();
// 访问结点
paraString += paraNode + " ";
visited[paraNode] = true;
tempQueue.enqueue(new Integer(paraNode));
while (!tempQueue.isEmpty()) {
int tempIndex = ((Integer) tempQueue.dequeue()).intValue();
for (int i = 0; i < paraNumberNode; i++) {
if (!visited[i] && connectivityMatrix.data[tempIndex][i] > 0) {
paraString += i + " ";
visited[i] = true;
tempQueue.enqueue(new Integer(i));
} // Of if
} // Of for i
} // Of while
return paraString;
}// Of breadthFirstVisit
/**
*
*********************
* @Title: breadthFirstTraverseTest
* @Description: TODO(Unit test for BFSTraverse)
*
*********************
*
*/
public static void breadthFirstTraverseTest() {
int[][] tempMatrix = { { 0, 1, 1, 0 }, { 1, 0, 0, 1 }, { 1, 0, 0, 1 }, { 0, 1, 1, 0 } };
Graph tempGraph = new Graph(tempMatrix);
System.out.println(tempGraph);
String tempSequence = "";
try {
tempSequence = tempGraph.breadthFirstTraverse(0);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e);
} // Of try
System.out.println("The breadth first order of visit: " + tempSequence + "\r\n");
int[][] tempMatrix2 = { { 0, 0, 0, 0 }, { 0, 0, 0, 1 }, { 0, 0, 0, 1 }, { 0, 1, 1, 0 } };
Graph tempGraph2 = new Graph(tempMatrix2);
System.out.println(tempGraph2);
String tempSequence2 = "";
try {
tempSequence2 = tempGraph2.depthFirstTraverse(3);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e);
} // Of try
System.out.println("The breadth first order of visit: " + tempSequence2 + "\r\n");
}// Of BFSTraverseTest
深度优先遍历:从一个结点v出发,找到一个与之相连的结点u,然后从结点u出发进行深度优先遍历,直到遍历完所有相连的结点。
同样需要考虑与广度优先遍历的两种情况。
深度优先遍历过程举例:
不难看出,深度优先遍历结点的存储特点是后进先出,所以可以考虑用栈或递归实现。
用递归实现代码:
/**
*
*********************
* @Title: deepthFirstTraverse
* @Description: TODO(To travel the graph with depth first.)
*
*********************
*
*/
public String depthFirstTraverse(int paraStartNode) {
String resultString = "";
int numberNodes = connectivityMatrix.getData().length;
initVisited(numberNodes);
resultString = depthFirsVisit(paraStartNode, resultString, numberNodes);
for (int i = 0; i < numberNodes; i++) {
if (!visited[i]) {
resultString = depthFirsVisit(i, resultString, numberNodes);
} // Of if
} // Of for i
return resultString;
}// Of depthFirstTraverse
/**
*
*********************
* @Title: depthFirsVisit
* @Description: TODO(To traverse the connected subgraph.)
*
* @param paraNode The start node.
* @param paraString The result.
* @param paraNumberNode The number of nodes.
*********************
*
*/
public String depthFirsVisit(int paraNode, String paraString, int paraNumberNode) {
paraString += paraNode + " ";
visited[paraNode] = true;
for (int i = 0; i < paraNumberNode; i++) {
if (!visited[i] && connectivityMatrix.data[paraNode][i] > 0) {
paraString = depthFirsVisit(i, paraString, paraNumberNode);
} // Of if
} // Of for i
return paraString;
}// Of depthFirsVisit
/**
*
*********************
* @Title: deepthFirstTraverseWithStack
* @Description: TODO(To travel the graph with depth first.)
*
*********************
*
*/
public String depthFirstTraverseWithStack(int paraStartNode) {
String resultString = "";
int numberNodes = connectivityMatrix.getData().length;
initVisited(numberNodes);
resultString = depthFirsVisitWithStack(paraStartNode, resultString, numberNodes);
for (int i = 0; i < numberNodes; i++) {
if (!visited[i]) {
resultString = depthFirsVisit(i, resultString, numberNodes);
} // Of if
} // Of for i
return resultString;
}// Of depthFirstTraverseWithStack
用栈实现代码:
/**
*
*********************
* @Title: deepthFirstTraverseWithStack
* @Description: TODO(To travel the graph with depth first.)
*
*********************
*
*/
public String depthFirstTraverseWithStack(int paraStartNode) {
String resultString = "";
int numberNodes = connectivityMatrix.getData().length;
initVisited(numberNodes);
resultString = depthFirsVisitWithStack(paraStartNode, resultString, numberNodes);
for (int i = 0; i < numberNodes; i++) {
if (!visited[i]) {
resultString = depthFirsVisit(i, resultString, numberNodes);
} // Of if
} // Of for i
return resultString;
}// Of depthFirstTraverseWithStack
/**
*
*********************
* @Title: depthFirsVisitWithStack
* @Description: TODO(To traverse the connected subgraph.)
*
* @param paraNode The start node.
* @param paraString The result.
* @param paraNumberNode The number of nodes.
*********************
*
*/
public String depthFirsVisitWithStack(int paraNode, String paraString, int paraNumberNode) {
ObjectStack tempStack = new ObjectStack();
paraString += paraNode + " ";
visited[paraNode] = true;
tempStack.push(new Integer(paraNode));
int tempIndex = paraNode;
while (tempIndex != -1) {
for (int i = 0; i < paraNumberNode; i++) {
if (!visited[i] && connectivityMatrix.data[tempIndex][i] > 0) {
paraString += i + " ";
visited[i] = true;
tempStack.push(i);
tempIndex = i;
i = -1;
} // Of if
} // Of for i
if (tempStack.isEmpty()) {
tempIndex = -1;
} else {
tempIndex = ((Integer) tempStack.pop()).intValue();
} // Of if
} // Of while
return paraString;
}// Of depthFirsVisitWithStack
深度优先遍历测试代码:
/**
*
*********************
* @Title: depthFirstTraverseTest
* @Description: TODO(Unit test for depthFirstTraverse and
* depthFirsVisitWithStack)
*
*********************
*
*/
public static void depthFirstTraverseTest() {
int[][] tempMatrix = { { 0, 1, 1, 0 }, { 1, 0, 0, 1 }, { 1, 0, 0, 1 }, { 0, 1, 1, 0 } };
Graph tempGraph = new Graph(tempMatrix);
System.out.println(tempGraph);
String tempSequence = "";
String tempSequenceStack = "";
try {
tempSequence = tempGraph.depthFirstTraverse(3);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e);
} // Of try
try {
tempSequenceStack = tempGraph.depthFirstTraverseWithStack(3);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e);
} // Of try
System.out.println("The depth first order of visit: " + tempSequence + "\r\n");
System.out.println("The depth first order of visit with stack: " + tempSequenceStack + "\r\n");
int[][] tempMatrix2 = { { 0, 1, 1, 0 }, { 1, 0, 0, 0 }, { 0, 0, 0, 1 }, { 0, 1, 1, 0 } };
Graph tempGraph2 = new Graph(tempMatrix2);
System.out.println(tempGraph2);
String tempSequence2 = "";
String tempSequenceStack2 = "";
try {
tempSequence2 = tempGraph2.depthFirstTraverse(1);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e);
} // Of try
try {
tempSequenceStack2 = tempGraph2.depthFirstTraverseWithStack(1);
} catch (Exception e) {
// TODO: handle exception
System.out.println(e);
} // Of try
System.out.println("The depth first order of visit: " + tempSequence2 + "\r\n");
System.out.println("The depth first order of visit with stack: " + tempSequenceStack2 + "\r\n");
}// Of depthFirstTraverseTest
运行结果: