总述
01-10天,基本语法
11-20天,线性数据结构
21-30天,树与二叉树
31-40天,图
41-50天,查找与排序
51-60天,kNN 与 NB
61-70天,决策树与集成学习
71-80天,BP 神经网络
81-90天,CNN 卷积神经网络
这个代码以前有基础. 原想着写矩阵连通性, 把这个当成开胃菜的, 后来发现这个的代码量已经够了. 良心发现, 把这个做成一天的工作.
package matrix;
import java.util.Arrays;
/**
* Int matrix. For efficiency we do not define ObjectMatrix. One can revise it
* to obtain DoubleMatrix.
*
* @author Fan Min [email protected].
*/
public class IntMatrix {
/**
* The data.
*/
int[][] data;
/**
*********************
* The first constructor.
*
* @param paraRows
* The number of rows.
* @param paraColumns
* The number of columns.
*********************
*/
public IntMatrix(int paraRows, int paraColumns) {
data = new int[paraRows][paraColumns];
}// Of the first constructor
/**
*********************
* The second constructor. Construct a copy of the given matrix.
*
* @param paraMatrix
* The given matrix.
*********************
*/
public IntMatrix(int[][] paraMatrix) {
data = new int[paraMatrix.length][paraMatrix[0].length];
// Copy elements.
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[0].length; j++) {
data[i][j] = paraMatrix[i][j];
} // Of for j
} // Of for i
}// Of the second constructor
/**
*********************
* The third constructor. Construct a copy of the given matrix.
*
* @param paraMatrix
* The given matrix.
*********************
*/
public IntMatrix(IntMatrix paraMatrix) {
this(paraMatrix.getData());
}// Of the third constructor
/**
*********************
* Get identity matrix. The values at the diagonal are all 1.
*
* @param paraRows
* The given rows.
*********************
*/
public static IntMatrix getIdentityMatrix(int paraRows) {
IntMatrix resultMatrix = new IntMatrix(paraRows, paraRows);
for (int i = 0; i < paraRows; i++) {
// According to access control, resultMatrix.data can be visited
// directly.
resultMatrix.data[i][i] = 1;
} // Of for i
return resultMatrix;
}// Of getIdentityMatrix
/**
*********************
* Overrides the method claimed in Object, the superclass of any class.
*********************
*/
public String toString() {
return Arrays.deepToString(data);
}// Of toString
/**
*********************
* Get my data. Warning, the reference to the data instead of a copy of the
* data is returned.
*
* @return The data matrix.
*********************
*/
public int[][] getData() {
return data;
}// Of getData
/**
*********************
* Getter.
*
* @return The number of rows.
*********************
*/
public int getRows() {
return data.length;
}// Of getRows
/**
*********************
* Getter.
*
* @return The number of columns.
*********************
*/
public int getColumns() {
return data[0].length;
}// Of getColumns
/**
*********************
* Set one the value of one element.
*
* @param paraRow
* The row of the element.
* @param paraColumn
* The column of the element.
* @param paraValue
* The new value.
*********************
*/
public void setValue(int paraRow, int paraColumn, int paraValue) {
data[paraRow][paraColumn] = paraValue;
}// Of setValue
/**
*********************
* Get the value of one element.
*
* @param paraRow
* The row of the element.
* @param paraColumn
* The column of the element.
*********************
*/
public int getValue(int paraRow, int paraColumn) {
return data[paraRow][paraColumn];
}// Of getValue
/**
*********************
* Add another matrix to me.
*
* @param paraMatrix
* The other matrix.
*********************
*/
public void add(IntMatrix paraMatrix) throws Exception {
// Step 1. Get the data of the given matrix.
int[][] tempData = paraMatrix.getData();
// Step 2. Size check.
if (data.length != tempData.length) {
throw new Exception("Cannot add matrices. Rows not match: " + data.length + " vs. "
+ tempData.length + ".");
} // Of if
if (data[0].length != tempData[0].length) {
throw new Exception("Cannot add matrices. Rows not match: " + data[0].length + " vs. "
+ tempData[0].length + ".");
} // Of if
// Step 3. Add to me.
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[0].length; j++) {
data[i][j] += tempData[i][j];
} // Of for j
} // Of for i
}// Of add
/**
*********************
* Add two existing matrices.
*
* @param paraMatrix1
* The first matrix.
* @param paraMatrix2
* The second matrix.
* @return A new matrix.
*********************
*/
public static IntMatrix add(IntMatrix paraMatrix1, IntMatrix paraMatrix2) throws Exception {
// Step 1. Clone the first matrix.
IntMatrix resultMatrix = new IntMatrix(paraMatrix1);
// Step 2. Add the second one.
resultMatrix.add(paraMatrix2);
return resultMatrix;
}// Of add
/**
*********************
* Multiply two existing matrices.
*
* @param paraMatrix1
* The first matrix.
* @param paraMatrix2
* The second matrix.
* @return A new matrix.
*********************
*/
public static IntMatrix multiply(IntMatrix paraMatrix1, IntMatrix paraMatrix2)
throws Exception {
// Step 1. Check size.
int[][] tempData1 = paraMatrix1.getData();
int[][] tempData2 = paraMatrix2.getData();
if (tempData1[0].length != tempData2.length) {
throw new Exception("Cannot multiply matrices: " + tempData1[0].length + " vs. "
+ tempData2.length + ".");
} // Of if
// Step 2. Allocate space.
int[][] resultData = new int[tempData1.length][tempData2[0].length];
// Step 3. Multiply.
for (int i = 0; i < tempData1.length; i++) {
for (int j = 0; j < tempData2[0].length; j++) {
for (int k = 0; k < tempData1[0].length; k++) {
resultData[i][j] += tempData1[i][k] * tempData2[k][j];
} // Of for k
} // Of for j
} // Of for i
// Step 4. Construct the matrix object.
IntMatrix resultMatrix = new IntMatrix(resultData);
return resultMatrix;
}// Of multiply
/**
*********************
* The entrance of the program.
*
* @param args
* Not used now.
*********************
*/
public static void main(String args[]) {
IntMatrix tempMatrix1 = new IntMatrix(3, 3);
tempMatrix1.setValue(0, 1, 1);
tempMatrix1.setValue(1, 0, 1);
tempMatrix1.setValue(1, 2, 1);
tempMatrix1.setValue(2, 1, 1);
System.out.println("The original matrix is: " + tempMatrix1);
IntMatrix tempMatrix2 = null;
try {
tempMatrix2 = IntMatrix.multiply(tempMatrix1, tempMatrix1);
} catch (Exception ee) {
System.out.println(ee);
} // Of try
System.out.println("The square matrix is: " + tempMatrix2);
IntMatrix tempMatrix3 = new IntMatrix(tempMatrix2);
try {
tempMatrix3.add(tempMatrix1);
} catch (Exception ee) {
System.out.println(ee);
} // Of try
System.out.println("The connectivity matrix is: " + tempMatrix3);
}// Of main
}// Of class IntMatrix
令图的连通矩阵为 M M M, M 0 = I M^0 = I M0=I 为单位矩阵. 要知道图的连通性, 只需要计算 M a = M 0 + M 1 + ⋯ + M n − 1 M_a = M^0 + M^1 + \dots + M^{n - 1} Ma=M0+M1+⋯+Mn−1, 其中 n n n 是节点个数. M a M_a Ma 中第 i i i 行第 j j j 列元素为 0 的话, 就表示从节点 i i i 到节点 j j j 不可达.
package datastructure.graph;
import matrix.IntMatrix;
/**
* Directed graph. Note that undirected graphs are a special case of directed
* graphs.
*
* @author Fan Min [email protected].
*/
public class Graph {
/**
* The connectivity matrix.
*/
IntMatrix connectivityMatrix;
/**
*********************
* The first constructor.
*
* @param paraNumNodes
* The number of nodes in the graph.
*********************
*/
public Graph(int paraNumNodes) {
connectivityMatrix = new IntMatrix(paraNumNodes, paraNumNodes);
}// Of the first constructor
/**
*********************
* The second constructor.
*
* @param paraMatrix
* The data matrix.
*********************
*/
public Graph(int[][] paraMatrix) {
connectivityMatrix = new IntMatrix(paraMatrix);
}// Of the second constructor
/**
*********************
* Overrides the method claimed in Object, the superclass of any class.
*********************
*/
public String toString() {
String resultString = "This is the connectivity matrix of the graph.\r\n"
+ connectivityMatrix;
return resultString;
}// Of toString
/**
*********************
* Get the connectivity of the graph.
*
* @throws Exception
* for internal error.
*********************
*/
public boolean getConnectivity() throws Exception {
// Step 1. Initialize accumulated matrix: M_a = I.
IntMatrix tempConnectivityMatrix = IntMatrix
.getIdentityMatrix(connectivityMatrix.getData().length);
// Step 2. Initialize M^1.
IntMatrix tempMultipliedMatrix = new IntMatrix(connectivityMatrix);
// Step 3. Determine the actual connectivity.
for (int i = 0; i < connectivityMatrix.getData().length - 1; i++) {
// M_a = M_a + M^k
tempConnectivityMatrix.add(tempMultipliedMatrix);
// M^k
tempMultipliedMatrix = IntMatrix.multiply(tempMultipliedMatrix, connectivityMatrix);
} // Of for i
// Step 4. Check the connectivity.
System.out.println("The connectivity matrix is: " + tempConnectivityMatrix);
int[][] tempData = tempConnectivityMatrix.getData();
for (int i = 0; i < tempData.length; i++) {
for (int j = 0; j < tempData.length; j++) {
if (tempData[i][j] == 0) {
System.out.println("Node " + i + " cannot reach " + j);
return false;
} // Of if
} // Of for j
} // Of for i
return true;
}// Of getConnectivity
/**
*********************
* Unit test for getConnectivity.
*********************
*/
public static void getConnectivityTest() {
// Test an undirected graph.
int[][] tempMatrix = { { 0, 1, 0 }, { 1, 0, 1 }, { 0, 1, 0 } };
Graph tempGraph2 = new Graph(tempMatrix);
System.out.println(tempGraph2);
boolean tempConnected = false;
try {
tempConnected = tempGraph2.getConnectivity();
} catch (Exception ee) {
System.out.println(ee);
} // Of try.
System.out.println("Is the graph connected? " + tempConnected);
// Test a directed graph.
// Remove one arc to form a directed graph.
tempGraph2.connectivityMatrix.setValue(1, 0, 0);
tempConnected = false;
try {
tempConnected = tempGraph2.getConnectivity();
} catch (Exception ee) {
System.out.println(ee);
} // Of try.
System.out.println("Is the graph connected? " + tempConnected);
}// Of getConnectivityTest
/**
*********************
* The entrance of the program.
*
* @param args
* Not used now.
*********************
*/
public static void main(String args[]) {
System.out.println("Hello!");
Graph tempGraph = new Graph(3);
System.out.println(tempGraph);
// Unit test.
getConnectivityTest();
}// Of main
}// Of class Graph
/**
*********************
* 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 = "";
int tempNumNodes = connectivityMatrix.getRows();
boolean[] tempVisitedArray = new boolean[tempNumNodes];
//Initialize the queue.
//Visit before enqueue.
tempVisitedArray[paraStartIndex] = true;
resultString += paraStartIndex;
tempQueue.enqueue(new Integer(paraStartIndex));
//Now visit the rest of the graph.
int tempIndex;
Integer tempInteger = (Integer)tempQueue.dequeue();
while (tempInteger != null) {
tempIndex = tempInteger.intValue();
//Enqueue all its unvisited neighbors.
for (int i = 0; i < tempNumNodes; i ++) {
if (tempVisitedArray[i]) {
continue; //Already visited.
}//Of if
if (connectivityMatrix.getData()[tempIndex][i] == 0) {
continue; //Not directly connected.
}//Of if
//Visit before enqueue.
tempVisitedArray[i] = true;
resultString += i;
tempQueue.enqueue(new Integer(i));
}//Of for i
//Take out one from the head.
tempInteger = (Integer)tempQueue.dequeue();
}//Of while
return resultString;
}//Of breadthFirstTraversal
/**
*********************
* Unit test for breadthFirstTraversal.
*********************
*/
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} };
Graph tempGraph = new Graph(tempMatrix);
System.out.println(tempGraph);
String tempSequence = "";
try {
tempSequence = tempGraph.breadthFirstTraversal(2);
} catch (Exception ee) {
System.out.println(ee);
} // Of try.
System.out.println("The breadth first order of visit: " + tempSequence);
}//Of breadthFirstTraversalTest
/**
*********************
* The entrance of the program.
*
* @param args
* Not used now.
*********************
*/
public static void main(String args[]) {
System.out.println("Hello!");
Graph tempGraph = new Graph(3);
System.out.println(tempGraph);
// Unit test.
getConnectivityTest();
breadthFirstTraversalTest();
}// Of main
/**
*********************
* 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 = "";
int tempNumNodes = connectivityMatrix.getRows();
boolean[] tempVisitedArray = new boolean[tempNumNodes];
//Initialize the stack.
//Visit before push.
tempVisitedArray[paraStartIndex] = true;
resultString += paraStartIndex;
tempStack.push(new Integer(paraStartIndex));
System.out.println("Push " + paraStartIndex);
System.out.println("Visited " + resultString);
//Now visit the rest of the graph.
int tempIndex = paraStartIndex;
int tempNext;
Integer tempInteger;
while (true){
//Find an unvisited neighbor.
tempNext = -1;
for (int i = 0; i < tempNumNodes; i ++) {
if (tempVisitedArray[i]) {
continue; //Already visited.
}//Of if
if (connectivityMatrix.getData()[tempIndex][i] == 0) {
continue; //Not directly connected.
}//Of if
//Visit this one.
tempVisitedArray[i] = true;
resultString += i;
tempStack.push(new Integer(i));
System.out.println("Push " + i);
tempNext = i;
//One is enough.
break;
}//Of for i
if (tempNext == -1) {
tempInteger = (Integer) tempStack.pop();
System.out.println("Pop " + tempInteger);
if (tempStack.isEmpty()) {
// No unvisited neighbor. Backtracking to the last one
// stored in the stack.
// Attention: This is the terminate condition!
break;
} else {
// Back to the previous node, however do not remove it.
tempInteger = (Integer) tempStack.pop();
tempIndex = tempInteger.intValue();
tempStack.push(tempInteger);
} // Of if
} else {
tempIndex = tempNext;
} // Of if
}//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[]) {
System.out.println("Hello!");
Graph tempGraph = new Graph(3);
System.out.println(tempGraph);
// Unit test.
getConnectivityTest();
breadthFirstTraversalTest();
depthFirstTraversalTest();
}// Of main
/**
*********************
* Coloring. Output all possible schemes.
*
* @param paraNumColors The number of colors.
*********************
*/
public void coloring(int paraNumColors) {
// Step 1. Initialize.
int tempNumNodes = connectivityMatrix.getRows();
int[] tempColorScheme = new int[tempNumNodes];
Arrays.fill(tempColorScheme, -1);
coloring(paraNumColors, 0, tempColorScheme);
}// Of coloring
/**
*********************
* Coloring. Output all possible schemes.
*
* @param paraNumColors The number of colors.
* @param paraCurrentNumNodes The number of nodes that have been colored.
* @param paraCurrentColoring The array recording the coloring scheme.
*********************
*/
public void coloring(int paraNumColors, int paraCurrentNumNodes, int[] paraCurrentColoring) {
// Step 1. Initialize.
int tempNumNodes = connectivityMatrix.getRows();
System.out.println("coloring: paraNumColors = " + paraNumColors + ", paraCurrentNumNodes = "
+ paraCurrentNumNodes + ", paraCurrentColoring" + Arrays.toString(paraCurrentColoring));
// A complete scheme.
if (paraCurrentNumNodes >= tempNumNodes) {
System.out.println("Find one:" + Arrays.toString(paraCurrentColoring));
return;
} // Of if
// Try all possible colors.
for (int i = 0; i < paraNumColors; i++) {
paraCurrentColoring[paraCurrentNumNodes] = i;
if (!colorConflict(paraCurrentNumNodes + 1, paraCurrentColoring)) {
coloring(paraNumColors, paraCurrentNumNodes + 1, paraCurrentColoring);
} // Of if
} // Of for i
}// Of coloring
/**
*********************
* Coloring conflict or not. Only compare the current last node with previous
* ones.
*
* @param paraCurrentNumNodes The current number of nodes.
* @param paraColoring The current coloring scheme.
* @return Conflict or not.
*********************
*/
public boolean colorConflict(int paraCurrentNumNodes, int[] paraColoring) {
for (int i = 0; i < paraCurrentNumNodes - 1; i++) {
// No direct connection.
if (connectivityMatrix.getValue(paraCurrentNumNodes - 1, i) == 0) {
continue;
} // Of if
if (paraColoring[paraCurrentNumNodes - 1] == paraColoring[i]) {
return true;
} // Of if
} // Of for i
return false;
}// Of colorConflict
/**
*********************
* Coloring test.
*********************
*/
public static void coloringTest() {
int[][] tempMatrix = { { 0, 1, 1, 0 }, { 1, 0, 0, 1 }, { 1, 0, 0, 0 }, { 0, 1, 0, 0 } };
Graph tempGraph = new Graph(tempMatrix);
//tempGraph.coloring(2);
tempGraph.coloring(3);
}// Of coloringTest
/**
*********************
* The entrance of the program.
*
* @param args Not used now.
*********************
*/
public static void main(String args[]) {
System.out.println("Hello!");
Graph tempGraph = new Graph(3);
System.out.println(tempGraph);
// Unit test.
getConnectivityTest();
breadthFirstTraversalTest();
depthFirstTraversalTest();
coloringTest();
}// Of main
package datastructure.graph;
import datastructure.queue.CircleObjectQueue;
/**
* Adjacency list for directed graph.
*
* @author Fan Min [email protected].
*/
public class AdjacencyList {
/**
* An inner class for adjacent node.
*/
class AdjacencyNode {
/**
* The column index.
*/
int column;
/**
* The next adjacent node.
*/
AdjacencyNode next;
/**
*********************
* The first constructor.
*
* @param paraColumn
* The column.
*********************
*/
public AdjacencyNode(int paraColumn) {
column = paraColumn;
next = null;
}// Of AdjacencyNode
}// Of class AdjacencyNode
/**
* The number of nodes. This member variable may be redundant since it is
* always equal to headers.length.
*/
int numNodes;
/**
* The headers for each row.
*/
AdjacencyNode[] headers;
/**
*********************
* The first constructor.
*
* @param paraMatrix
* The the matrix indicating the graph.
*********************
*/
public AdjacencyList(int[][] paraMatrix) {
numNodes = paraMatrix.length;
// Step 1. Initialize. The data in the headers are not meaningful.
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
// Create a new node.
tempNode = new AdjacencyNode(j);
// Link.
tempPreviousNode.next = tempNode;
tempPreviousNode = tempNode;
} // Of for j
} // Of for i
}// Of class AdjacentTable
/**
*********************
* Overrides the method claimed in Object, the superclass of any class.
*********************
*/
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];
tempVisitedArray[paraStartIndex] = true;
// Initialize the queue.
// Visit before enqueue.
tempVisitedArray[paraStartIndex] = true;
resultString += paraStartIndex;
tempQueue.enqueue(new Integer(paraStartIndex));
// Now visit the rest of the graph.
int tempIndex;
Integer tempInteger = (Integer) tempQueue.dequeue();
AdjacencyNode tempNode;
while (tempInteger != null) {
tempIndex = tempInteger.intValue();
// Enqueue all its unvisited neighbors. The neighbors are linked
// already.
tempNode = headers[tempIndex].next;
while (tempNode != null) {
if (!tempVisitedArray[tempNode.column]) {
// Visit before enqueue.
tempVisitedArray[tempNode.column] = true;
resultString += tempNode.column;
tempQueue.enqueue(new Integer(tempNode.column));
} // 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 } };
Graph tempGraph = new Graph(tempMatrix);
System.out.println(tempGraph);
AdjacencyList tempAdjList = new AdjacencyList(tempMatrix);
String tempSequence = "";
try {
tempSequence = tempAdjList.breadthFirstTraversal(2);
} catch (Exception ee) {
System.out.println(ee);
} // Of try.
System.out.println("The breadth first order of visit: " + tempSequence);
}// Of breadthFirstTraversalTest
/**
*********************
* 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();
}// Of main
}// Of class AdjacencyList
package datastructure.graph;
/**
* Orthogonal List for directed graph.
*
* @author Fan Min [email protected].
*/
public class OrthogonalList {
/**
* An inner class for adjacent node.
*/
class OrthogonalNode {
/**
* The row index.
*/
int row;
/**
* The column index.
*/
int column;
/**
* The next out node.
*/
OrthogonalNode nextOut;
/**
* The next in node.
*/
OrthogonalNode nextIn;
/**
*********************
* The first constructor.
*
* @param paraRow The row.
* @param paraColumn The column.
*********************
*/
public OrthogonalNode(int paraRow, int paraColumn) {
row = paraRow;
column = paraColumn;
nextOut = null;
nextIn = null;
}// Of OrthogonalNode
}// Of class OrthogonalNode
/**
* The number of nodes. This member variable may be redundant since it is always
* equal to headers.length.
*/
int numNodes;
/**
* The headers for each row.
*/
OrthogonalNode[] headers;
/**
*********************
* The first constructor.
*
* @param paraMatrix The matrix indicating the graph.
*********************
*/
public OrthogonalList(int[][] paraMatrix) {
numNodes = paraMatrix.length;
// Step 1. Initialize. The data in the headers are not meaningful.
OrthogonalNode tempPreviousNode, tempNode;
headers = new OrthogonalNode[numNodes];
// Step 2. Link to its out nodes.
for (int i = 0; i < numNodes; i++) {
headers[i] = new OrthogonalNode(i, -1);
tempPreviousNode = headers[i];
for (int j = 0; j < numNodes; j++) {
if (paraMatrix[i][j] == 0) {
continue;
} // Of if
// Create a new node.
tempNode = new OrthogonalNode(i, j);
// Link.
tempPreviousNode.nextOut = tempNode;
tempPreviousNode = tempNode;
} // Of for j
} // Of for i
// Step 3. Link to its in nodes. This step is harder.
OrthogonalNode[] tempColumnNodes = new OrthogonalNode[numNodes];
for (int i = 0; i < numNodes; i++) {
tempColumnNodes[i] = headers[i];
} // Of for i
for (int i = 0; i < numNodes; i++) {
tempNode = headers[i].nextOut;
while (tempNode != null) {
tempColumnNodes[tempNode.column].nextIn = tempNode;
tempColumnNodes[tempNode.column] = tempNode;
tempNode = tempNode.nextOut;
} // Of while
} // Of for i
}// Of the constructor
/**
*********************
* Overrides the method claimed in Object, the superclass of any class.
*********************
*/
public String toString() {
String resultString = "Out arcs: ";
OrthogonalNode tempNode;
for (int i = 0; i < numNodes; i++) {
tempNode = headers[i].nextOut;
while (tempNode != null) {
resultString += " (" + tempNode.row + ", " + tempNode.column + ")";
tempNode = tempNode.nextOut;
} // Of while
resultString += "\r\n";
} // Of for i
resultString += "\r\nIn arcs: ";
for (int i = 0; i < numNodes; i++) {
tempNode = headers[i].nextIn;
while (tempNode != null) {
resultString += " (" + tempNode.row + ", " + tempNode.column + ")";
tempNode = tempNode.nextIn;
} // Of while
resultString += "\r\n";
} // Of for i
return resultString;
}// Of toString
/**
*********************
* The entrance of the program.
*
* @param args Not used now.
*********************
*/
public static void main(String args[]) {
int[][] tempMatrix = { { 0, 1, 0, 0 }, { 0, 0, 0, 1 }, { 1, 0, 0, 0 }, { 0, 1, 1, 0 } };
OrthogonalList tempList = new OrthogonalList(tempMatrix);
System.out.println("The data are:\r\n" + tempList);
}// Of main
}// Of class OrthogonalList
package datastructure.graph;
import java.util.Arrays;
import matrix.IntMatrix;
/**
* Weighted graphs are called nets.
*
* @author Fan Min [email protected].
*/
public class Net {
/**
* The maximal distance. Do not use Integer.MAX_VALUE.
*/
public static final int MAX_DISTANCE = 10000;
/**
* The number of nodes.
*/
int numNodes;
/**
* The weight matrix. We use int to represent weight for simplicity.
*/
IntMatrix weightMatrix;
/**
*********************
* The first constructor.
*
* @param paraNumNodes
* The number of nodes in the graph.
*********************
*/
public Net(int paraNumNodes) {
numNodes = paraNumNodes;
weightMatrix = new IntMatrix(numNodes, numNodes);
for (int i = 0; i < numNodes; i++) {
// For better readability, you may need to write fill() in class
// IntMatrix.
Arrays.fill(weightMatrix.getData()[i], MAX_DISTANCE);
} // Of for i
}// Of the first constructor
/**
*********************
* The second constructor.
*
* @param paraMatrix
* The data matrix.
*********************
*/
public Net(int[][] paraMatrix) {
weightMatrix = new IntMatrix(paraMatrix);
numNodes = weightMatrix.getRows();
}// Of the second constructor
/**
*********************
* Overrides the method claimed in Object, the superclass of any class.
*********************
*/
public String toString() {
String resultString = "This is the weight matrix of the graph.\r\n" + weightMatrix;
return resultString;
}// Of toString
/**
*********************
* The Dijkstra algorithm: shortest path from the source to all nodes.
*
* @param paraSource
* The source node.
* @return The distances to all nodes.
*********************
*/
public int[] dijkstra(int paraSource) {
// Step 1. Initialize.
int[] tempDistanceArray = new int[numNodes];
for (int i = 0; i < numNodes; i++) {
tempDistanceArray[i] = weightMatrix.getValue(paraSource, i);
} // Of for i
int[] tempParentArray = new int[numNodes];
Arrays.fill(tempParentArray, paraSource);
// -1 for no parent.
tempParentArray[paraSource] = -1;
// Visited nodes will not be considered further.
boolean[] tempVisitedArray = new boolean[numNodes];
tempVisitedArray[paraSource] = true;
// Step 2. Main loops.
int tempMinDistance;
int tempBestNode = -1;
for (int i = 0; i < numNodes - 1; i++) {
// Step 2.1 Find out the best next node.
tempMinDistance = Integer.MAX_VALUE;
for (int j = 0; j < numNodes; j++) {
// This node is visited.
if (tempVisitedArray[j]) {
continue;
} // Of if
if (tempMinDistance > tempDistanceArray[j]) {
tempMinDistance = tempDistanceArray[j];
tempBestNode = j;
} // Of if
} // Of for j
tempVisitedArray[tempBestNode] = true;
// Step 2.2 Prepare for the next round.
for (int j = 0; j < numNodes; j++) {
// This node is visited.
if (tempVisitedArray[j]) {
continue;
} // Of if
// This node cannot be reached.
if (weightMatrix.getValue(tempBestNode, j) >= MAX_DISTANCE) {
continue;
} // Of if
if (tempDistanceArray[j] > tempDistanceArray[tempBestNode]
+ weightMatrix.getValue(tempBestNode, j)) {
// Change the distance.
tempDistanceArray[j] = tempDistanceArray[tempBestNode]
+ weightMatrix.getValue(tempBestNode, j);
// Change the parent.
tempParentArray[j] = tempBestNode;
} // Of if
} // Of for j
// For test
System.out.println("The distance to each node: " + Arrays.toString(tempDistanceArray));
System.out.println("The parent of each node: " + Arrays.toString(tempParentArray));
} // Of for i
// Step 3. Output for debug.
System.out.println("Finally");
System.out.println("The distance to each node: " + Arrays.toString(tempDistanceArray));
System.out.println("The parent of each node: " + Arrays.toString(tempParentArray));
return tempDistanceArray;
}// Of dijkstra
/**
*********************
* The minimal spanning tree.
*
* @return The total cost of the tree.
*********************
*/
public int prim() {
// Step 1. Initialize.
// Any node can be the source.
int tempSource = 0;
int[] tempDistanceArray = new int[numNodes];
for (int i = 0; i < numNodes; i++) {
tempDistanceArray[i] = weightMatrix.getValue(tempSource, i);
} // Of for i
int[] tempParentArray = new int[numNodes];
Arrays.fill(tempParentArray, tempSource);
// -1 for no parent.
tempParentArray[tempSource] = -1;
// Visited nodes will not be considered further.
boolean[] tempVisitedArray = new boolean[numNodes];
tempVisitedArray[tempSource] = true;
// Step 2. Main loops.
int tempMinDistance;
int tempBestNode = -1;
for (int i = 0; i < numNodes - 1; i++) {
// Step 2.1 Find out the best next node.
tempMinDistance = Integer.MAX_VALUE;
for (int j = 0; j < numNodes; j++) {
// This node is visited.
if (tempVisitedArray[j]) {
continue;
} // Of if
if (tempMinDistance > tempDistanceArray[j]) {
tempMinDistance = tempDistanceArray[j];
tempBestNode = j;
} // Of if
} // Of for j
tempVisitedArray[tempBestNode] = true;
// Step 2.2 Prepare for the next round.
for (int j = 0; j < numNodes; j++) {
// This node is visited.
if (tempVisitedArray[j]) {
continue;
} // Of if
// This node cannot be reached.
if (weightMatrix.getValue(tempBestNode, j) >= MAX_DISTANCE) {
continue;
} // Of if
// Attention: the difference from the Dijkstra algorithm.
if (tempDistanceArray[j] > weightMatrix.getValue(tempBestNode, j)) {
// Change the distance.
tempDistanceArray[j] = weightMatrix.getValue(tempBestNode, j);
// Change the parent.
tempParentArray[j] = tempBestNode;
} // Of if
} // Of for j
// For test
System.out.println(
"The selected distance for each node: " + Arrays.toString(tempDistanceArray));
System.out.println("The parent of each node: " + Arrays.toString(tempParentArray));
} // Of for i
int resultCost = 0;
for (int i = 0; i < numNodes; i++) {
resultCost += tempDistanceArray[i];
} // Of for i
// Step 3. Output for debug.
System.out.println("Finally");
System.out.println("The parent of each node: " + Arrays.toString(tempParentArray));
System.out.println("The total cost: " + resultCost);
return resultCost;
}// Of prim
/**
*********************
* The entrance of the program.
*
* @param args
* Not used now.
*********************
*/
public static void main(String args[]) {
Net tempNet0 = new Net(3);
System.out.println(tempNet0);
int[][] tempMatrix1 = { { 0, 9, 3, 6 }, { 5, 0, 2, 4 }, { 3, 2, 0, 1 }, { 2, 8, 7, 0 } };
Net tempNet1 = new Net(tempMatrix1);
System.out.println(tempNet1);
// Dijkstra
tempNet1.dijkstra(1);
// An undirected net is required.
int[][] tempMatrix2 = { { 0, 7, MAX_DISTANCE, 5, MAX_DISTANCE }, { 7, 0, 8, 9, 7 },
{ MAX_DISTANCE, 8, 0, MAX_DISTANCE, 5 }, { 5, 9, MAX_DISTANCE, 0, 15 },
{ MAX_DISTANCE, 7, 5, 15, 0 } };
Net tempNet2 = new Net(tempMatrix2);
tempNet2.prim();
}// Of main
}// Of class Net
/**
*********************
* Critical path. Net validity checks such as loop check not implemented.
* The source should be 0 and the destination should be n-1.
*
* @return The node sequence of the path.
*********************
*/
public boolean[] criticalPath() {
// One more value to save simple computation.
int tempValue;
// Step 1. The in-degree of each node.
int[] tempInDegrees = new int[numNodes];
for (int i = 0; i < numNodes; i++) {
for (int j = 0; j < numNodes; j++) {
if (weightMatrix.getValue(i, j) != -1) {
tempInDegrees[j]++;
} // Of if
} // Of for j
} // Of for i
System.out.println("In-degree of nodes: " + Arrays.toString(tempInDegrees));
// Step 2. Topology sorting.
int[] tempEarliestTimeArray = new int[numNodes];
for (int i = 0; i < numNodes; i++) {
// This node cannot be removed.
if (tempInDegrees[i] > 0) {
continue;
} // Of if
System.out.println("Removing " + i);
for (int j = 0; j < numNodes; j++) {
if (weightMatrix.getValue(i, j) != -1) {
tempValue = tempEarliestTimeArray[i] + weightMatrix.getValue(i, j);
if (tempEarliestTimeArray[j] < tempValue) {
tempEarliestTimeArray[j] = tempValue;
} // Of if
tempInDegrees[j]--;
} // Of if
} // Of for j
} // Of for i
System.out.println("Earlest start time: " + Arrays.toString(tempEarliestTimeArray));
// Step 3. The out-degree of each node.
int[] tempOutDegrees = new int[numNodes];
for (int i = 0; i < numNodes; i++) {
for (int j = 0; j < numNodes; j++) {
if (weightMatrix.getValue(i, j) != -1) {
tempOutDegrees[i]++;
} // Of if
} // Of for j
} // Of for i
System.out.println("Out-degree of nodes: " + Arrays.toString(tempOutDegrees));
// Step 4. Reverse topology sorting.
int[] tempLatestTimeArray = new int[numNodes];
for (int i = 0; i < numNodes; i++) {
tempLatestTimeArray[i] = tempEarliestTimeArray[numNodes - 1];
} // Of for i
for (int i = numNodes - 1; i >= 0; i--) {
// This node cannot be removed.
if (tempOutDegrees[i] > 0) {
continue;
} // Of if
System.out.println("Removing " + i);
for (int j = 0; j < numNodes; j++) {
if (weightMatrix.getValue(j, i) != -1) {
tempValue = tempLatestTimeArray[i] - weightMatrix.getValue(j, i);
if (tempLatestTimeArray[j] > tempValue) {
tempLatestTimeArray[j] = tempValue;
} // Of if
tempOutDegrees[j]--;
System.out.println("The out-degree of " + j + " decreases by 1.");
} // Of if
} // Of for j
} // Of for i
System.out.println("Latest start time: " + Arrays.toString(tempLatestTimeArray));
boolean[] resultCriticalArray = new boolean[numNodes];
for (int i = 0; i < numNodes; i++) {
if (tempEarliestTimeArray[i] == tempLatestTimeArray[i]) {
resultCriticalArray[i] = true;
} // Of if
} // Of for i
System.out.println("Critical array: " + Arrays.toString(resultCriticalArray));
System.out.print("Critical nodes: ");
for (int i = 0; i < numNodes; i++) {
if (resultCriticalArray[i]) {
System.out.print(" " + i);
} // Of if
} // Of for i
System.out.println();
return resultCriticalArray;
}// Of criticalPath
/**
*********************
* The entrance of the program.
*
* @param args
* Not used now.
*********************
*/
public static void main(String args[]) {
Net tempNet0 = new Net(3);
System.out.println(tempNet0);
int[][] tempMatrix1 = { { 0, 9, 3, 6 }, { 5, 0, 2, 4 }, { 3, 2, 0, 1 }, { 2, 8, 7, 0 } };
Net tempNet1 = new Net(tempMatrix1);
System.out.println(tempNet1);
// Dijkstra
tempNet1.dijkstra(1);
// An undirected net is required.
int[][] tempMatrix2 = { { 0, 7, MAX_DISTANCE, 5, MAX_DISTANCE }, { 7, 0, 8, 9, 7 },
{ MAX_DISTANCE, 8, 0, MAX_DISTANCE, 5 }, { 5, 9, MAX_DISTANCE, 0, 15, },
{ MAX_DISTANCE, 7, 5, 15, 0 } };
Net tempNet2 = new Net(tempMatrix2);
tempNet2.prim();
// A directed net without loop is required.
// Node cannot reach itself. It is indicated by -1.
int[][] tempMatrix3 = { { -1, 3, 2, -1, -1, -1 }, { -1, -1, -1, 2, 3, -1 },
{ -1, -1, -1, 4, -1, 3 }, { -1, -1, -1, -1, -1, 2 }, { -1, -1, -1, -1, -1, 1 },
{ -1, -1, -1, -1, -1, -1 } };
Net tempNet3 = new Net(tempMatrix3);
System.out.println("-------critical path");
tempNet3.criticalPath();
}// Of main
描述这 10 天的学习体会, 不少于 10 条.