Day 36 —— Adjacency List
1. Background
学习java已经有36天了,今天学习的是图的邻接表表示,并完成深度优先遍历和广度优先遍历。
2. Description
今天数据结构方面没有什么可说的,还是图,只是换了一种表现形式。之前是一个矩阵,现在是一个个的链表。对于我来说,我比较喜欢邻接表,因为邻接表写深度优先和广度优先遍历方便。
3. Code
package datastructure.graph;
import datastructure.CircleObjectQueue;
import datastructure.ObjectStack;
public class AdjacencyList {
/**
* An inner class for adjacent node.
*/
class AdjacencyNode {
// 列数。
int column;
// 邻接表的下一个。
AdjacencyNode next;
/**
*********************
* The first constructor.
*
* @param paraColumn The column.
*********************
*/
public AdjacencyNode(int paraColumn) {
column = paraColumn;
next = null;
}// Of AdjacencyNode
}// Of class AdjacencyNode
// 节点数。
int numNodes;
// 每行的头节点。
AdjacencyNode[] headers;
/**
*********************
* The first constructor.
*
* @param paraMatrix The the matrix indicating the graph.
*********************
*/
public AdjacencyList(int[][] paraMatrix) {
numNodes = paraMatrix.length;
// Step 1. Initialize.
AdjacencyNode tempPreviousNode, tempNode;
headers = new AdjacencyNode[numNodes];
for (int i = 0; i < numNodes; i++) {
headers[i] = new AdjacencyNode(-1);
tempPreviousNode = headers[i];
for (int j = 0; j < numNodes; j++) {
if (paraMatrix[i][j] == 0) {
continue;
} // Of if
// 创建一个新的节点。
tempNode = new AdjacencyNode(j);
// 链接上面的节点
tempPreviousNode.next = tempNode;
tempPreviousNode = tempNode;
} // Of for j
} // Of for i
}// Of class AdjacentTable
// 经典的toString方法.
public String toString() {
String resultString = "";
AdjacencyNode tempNode;
for (int i = 0; i < numNodes; i++) {
tempNode = headers[i].next;
while (tempNode != null) {
resultString += " (" + i + ", " + tempNode.column + ")";
tempNode = tempNode.next;
} // Of while
resultString += "\r\n";
} // Of for i
return resultString;
}// Of toString
/**
*********************
* Breadth first traversal.
*
* @param paraStartIndex The start index.
* @return The sequence of the visit.
*********************
*/
public String breadthFirstTraversal(int paraStartIndex) {
CircleObjectQueue tempQueue = new CircleObjectQueue();
String resultString = "";
boolean[] tempVisitedArray = new boolean[numNodes];
// 深度优先遍历的开头,即对起始节点(paraStartIndex)进行处理。
tempVisitedArray[paraStartIndex] = true;
resultString += paraStartIndex;
Integer tempIndexInteger = Integer.valueOf(paraStartIndex);
tempQueue.enQueue(tempIndexInteger); // 入队起始节点.
// 访问表的剩余部分。
int tempIndex;
Integer tempInteger = (Integer) tempQueue.deQueue();
AdjacencyNode tempNode;
while (tempInteger != null) {
tempIndex = tempInteger.intValue();
// 将剩下的相邻的节点入队
tempNode = headers[tempIndex].next;
while (tempNode != null) {
if (!tempVisitedArray[tempNode.column]) {
// Visit before enqueue.
tempVisitedArray[tempNode.column] = true;
resultString += tempNode.column;
Integer tempInteger2 = Integer.valueOf(tempNode.column);
tempQueue.enQueue(tempInteger2);
} // Of if
tempNode = tempNode.next;
} // Of for i
// Take out one from the head.
tempInteger = (Integer) tempQueue.deQueue();
} // Of while
return resultString;
}// Of breadthFirstTraversal
/**
*********************
* Unit test for breadthFirstTraversal. The same as the one in class Graph.
*********************
*/
public static void breadthFirstTraversalTest() {
// Test an undirected graph.
int[][] tempMatrix = { { 0, 1, 1, 0 }, { 1, 0, 0, 1 }, { 1, 0, 0, 1 }, { 0, 1, 1, 0 } };
AdjacencyList tempAdjacencyList = new AdjacencyList(tempMatrix);
System.out.println(tempAdjacencyList);
String tempSequence = "";
try {
tempSequence = tempAdjacencyList.breadthFirstTraversal(2);
} catch (Exception ee) {
System.out.println(ee);
} // Of try.
System.out.println("The breadth first order of visit: " + tempSequence);
}// Of breadthFirstTraversalTest
/**
*********************
* Depth first traversal.
*
* @param paraStartIndex The start index.
* @return The sequence of the visit.
*********************
*/
public String depthFirstTraversal(int paraStartIndex) {
ObjectStack tempStack = new ObjectStack();
String resultString = "";
boolean[] tempVisitedArray = new boolean[numNodes];
// 初始化栈,并对给定的初始点进行处理,让它进栈。
tempVisitedArray[paraStartIndex] = true;
resultString += paraStartIndex;
AdjacencyNode tempNode = headers[paraStartIndex];
tempStack.Push(tempNode);
// 深度优先遍历的主体,对当前栈顶元素的下家进行入栈操作。
while (true){
if (tempNode.next != null && tempVisitedArray[tempNode.next.column]) {
tempNode = tempNode.next;
}
if (tempNode.next == null) {
tempNode = (AdjacencyNode) tempStack.Pop();
continue;
}
resultString += tempNode.next.column;
tempStack.Push(tempNode.next);
tempVisitedArray[tempNode.next.column] = true;
tempNode = headers[tempNode.next.column];
if (tempNode.next == null && tempStack.isEmpty()) {
break;
}
}//Of while
return resultString;
}//Of depthFirstTraversal
/**
*********************
* Unit test for depthFirstTraversal.
*********************
*/
public static void depthFirstTraversalTest() {
// Test an undirected graph.
int[][] tempMatrix = { { 0, 1, 1, 0 }, { 1, 0, 0, 1 }, { 1, 0, 0, 0}, { 0, 1, 0, 0} };
Graph tempGraph = new Graph(tempMatrix);
System.out.println(tempGraph);
String tempSequence = "";
try {
tempSequence = tempGraph.depthFirstTraversal(0);
} catch (Exception ee) {
System.out.println(ee);
} // Of try.
System.out.println("The depth first order of visit: " + tempSequence);
}//Of depthFirstTraversalTest
/**
*********************
* The entrance of the program.
*
* @param args Not used now.
*********************
*/
public static void main(String args[]) {
int[][] tempMatrix = { { 0, 1, 0 }, { 1, 0, 1 }, { 0, 1, 0 } };
AdjacencyList tempTable = new AdjacencyList(tempMatrix);
System.out.println("The data are:\r\n" + tempTable);
breadthFirstTraversalTest();
depthFirstTraversalTest();
}// Of main
}
运行结果:
4 Issue
我一直有一个疑问,如果是下面这种图,应该怎么跑。起始节点为0.
它的邻接表如下:
按照我的理解它应该会在把0进栈,然后出栈之后立刻停下。