第31-40天

第31天:整数矩阵及其运算

今日所要学习的内容如下:

矩阵对象的创建.
getRows 等: getter, setter 在 java 里面很常用. 主要是为了访问控制.
整数矩阵的加法、乘法.
Exception 的抛出与捕获机制.
用 this 调用其它的构造方法以减少冗余代码.
代码看起来多, 但矩阵运算我们以前写过.
把数据类型修改成 double, 获得 DoubleMatrix.java, 以后会很有用.
getIdentityMatrix: 单位矩阵.
resultMatrix.data[i][i]: 成员变量的访问权限: 在同一类里面是可以直接使用的.
 

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 minfanphd@163.com.
 */
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

运行结果:

第32天:图的连通性检测.

令图的连通矩阵为M,若矩阵中第i行第j列元素为0,则表示i不可到达j,要知道图的连通性,则需计算M0+M1+M2+…+Mn-1得到的矩阵中是否有非零元素,如果有就不连通,否则是连通的。其中M0是单位矩阵。

package datastructure.graph;

import matrix.IntMatrix;

/**
 * Directed graph. Note that undirected graphs are a special case of directed
 * graphs.
 * 
 * @author Fan Min minfanphd@163.com.
 */
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

运行结果:

第33天:图的广度优先遍历

图(grath)由一个顶点(vertex)的有穷非空集合V(G)和一个弧(arc)的集合E(G)组成,通常记作G = (V,E)。图中的顶点就是数据结构中的数据元素,弧的集合E实际上是定义在顶点集合上的一个关系。以下用有序对,表示v到w的一条弧。弧有方向性,需以一带有箭头的线段表示,通常称v(没有箭头的出发端)为弧尾或始点称w(带有箭头的终止端)为弧头或终点,此时的图称为有向图。
无向图若图中从v到w有一条弧,同时在w到v也有一条弧,则以无序对(v,w)代替这两个有序对,表示w,v的一条边。此时的图在顶点之间不在强调方向的特征,称为无向图
下图中a是有向图
G1 = (V1,{A})
其中V1={A,B,C,D,E,F,G}
A1={,,,,,,,, 图b为无向图
G2 = (V2,{E2})
V2={A,B,C,D,E,F}
E2={(A,B),(A,C),(B,C),(B,E),(B,F),(C,F),(C,E),(C,D),(E,F)}

在实际应用中,图的弧或者边往往与具有一定意义的数相关,这些数为权分别称带有权的有向图和无向图为有向网和无向网


稀疏图和稠密图 n表示定点的个数,e表示边或者弧的数目,若e 的取值范围是(0,n(n-1)/2)则称具有这些边的无向图为完全图对于有向图则称有向完全图若e 度: = 入度+出度
入度:从节点出发的边的个数
出度:与入度相反
路径和回路
连通图和连通分量

	/**
	 *********************
	 * 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];
		
		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();
		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

运行结果:

第34天:图的深度优先遍历

深度优先遍历(dfs):
从图中某顶点v出发:
(1)访问顶点v;
(2)依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问;
(3)若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止。
 

	/**
	 *********************
	 * 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) {
				//No unvisited neighbor. Backtracking to the last one stored in the stack.
				//Attention: This is the terminate condition!
				if (tempStack.isEmpty()) {
					break;
				}//Of if
				tempInteger = (Integer)tempStack.pop();
				System.out.println("Pop " + tempInteger);
				tempIndex = tempInteger.intValue();
			} 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

运行结果:

第35天: 图的 m 着色问题

  1. 经典的回溯算法. 万能的暴力解题法, 一定要掌握啊!
  2. 调拭时注意 +1, -1 之类的下标控制.
  3. 单独写一个冲突检测方法.
  4. 由于它仅使用了图的连接性, 所以放在这个部分
	/**
	 *********************
	 * 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 approaches.
	 * 
	 * @param paraNumColors The number of colors.
	 * @return The sequence of the visit.
	 *********************
	 */
	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

第36天:邻链表

邻接矩阵是不错的⼀种图存储结构,但是我们也发现,对于边数相对顶点较少的图,这种结构是存在对存储空间的极大浪费的。比如说,如果我们要处理下图这样的稀疏有向图,邻接矩阵中除了arc[1][0]有权值外,没有其他弧,其实这些存储空间都浪费掉了。

因此选择一种新的数据结构来存储这种稀疏图则尤为重要了。此时则使用链表结构来存储原来的连接信息。

package datastructure.graph;

import datastructure.queue.CircleObjectQueue;

/**
 * Adjacent table for directed graph.
 * 
 * @author Fan Min minfanphd@163.com.
 */
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]) {
					continue; // Already visited.
				} // Of if

				// Visit before enqueue.
				tempVisitedArray[tempNode.column] = true;
				resultString += tempNode.column;
				tempQueue.enqueue(new Integer(tempNode.column));

				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);

		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[]) {
		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 AdjacentTable

第 37 天: 十字链表

package datastructure.graph;

/**
 * Orthogonal List for directed graph.
 * 
 * @author Fan Min minfanphd@163.com.
 */
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

运行结果:

第38天:Dijkstra 算法与 Prim 算法

迪杰斯特拉(Dijkstra)算法是单源最短路径算法,用于计算一个节点到其他节点的最短路径。
它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。
1.指定一个节点,例如要计算 ‘A’ 到其他节点的最短路径
2.引入两个集合(S、U),S集合包含已求出的最短路径的点(以及相应的最短长度),U集合包含未求出最短路径的点(以及A到该点的路径,如上图所示,A->C由于没有直接相连 初始时为∞)
3.初始化两个集合,S集合初始时 只有当前要计算的节点,A->A = 0
4.U集合初始时为 A->B = 4, A->C = ∞, A->D = 2, A->E = ∞
从U集合中找出路径最短的点,加入S集合,例如 A->D = 2
5.更新U集合路径,if ( ‘D 到 B,C,E 的距离’ + ‘AD 距离’ < ‘A 到 B,C,E 的距离’ ) 则更新U
6.循环执行 4、5 两步骤,直至遍历结束,得到A 到其他节点的最短路径

prim算法:
1.输入:一个加权连通图,其中顶点集合为V,边集合为E;
2.初始化:Vnew = {x},其中x为集合V中的任一节点(起始点),Enew = {},为空;
3.重复下列操作,直到Vnew = V:
a.在集合E中选取权值最小的边<u, v>,其中u为集合Vnew中的元素,而v不在Vnew集合当中,并且v∈V(如果存在有多条满足前述条件即具有相同权值的边,则可任意选取其中之一);
b.将v加入集合Vnew中,将<u, v>边加入集合Enew中;
4.输出:使用集合Vnew和Enew来描述所得到的最小生成树。
 

package datastructure.graph;

import java.util.Arrays;

import matrix.IntMatrix;

/**
 * Weighted graphs are called nets.
 * 
 * @author Fan Min minfanphd@163.com.
 */
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

 第39天:关键路径

拓扑排序是关键路径的一部分.
关键路径长度, 其实是最远路径长度. 然而, 它并非最短路径的对偶问题. 我尝试修改 Dijkstra 算法来解决, 然后发现自己傻了.
正向算每个节点的最早开始时间, 逆向算每个节点的最晚开始时间, 设计太了.
最晚开始时间的初始化容易弄错, 经典算法果然是不好对付的.
注释很多, 因为我自己花了两小时才弄明白. 大意了啊.
AOE网:在一个表示工程的带权有向图中,用顶点表示事件(如V0),用有向边表示活动(如<v0,v1> = a0),边上的权值表示活动的持续时间,称这样的有向图为边表示的活动的网,简称AOE网(activity on edge network)
如图,起点为V0,终点为V3.
1、只有在进入某顶点的活动都已经结束,该顶点所代表的事件才发生。例如:a1,a2活动都结束了,顶点V2所代表的事件才会发生。
2、只有在某顶点所代表的事件发生后,从该顶点出发的各活动才开始。例如:只有顶点V1所代表的事件结束之后,活动a2和a4才会开始。
 

	/**
	 *********************
	 * 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 for 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 for 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 for 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 for 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

第 40 天: 小结

1。学习了矩阵对象的创建.getRows 等: getter, setter 在 java 里面很常用. 主要是为了访问控制.整数矩阵的加法、乘法.
2.复习了矩阵运算,发现在图的算法中用矩阵运算会变得很方便;
3.检测图的连通性可以通过矩阵运算实现;
4.复习了dfs和bfs算法,前者用栈后者用队列;
5.复习了经典回溯图的m着色问题,就是dfs;
6.图的压缩存储方式是用邻接表,也可以组成十字链表,就是将有向图的邻接表和逆邻接表结合起来;
7.学习了迪杰斯特拉(Dijkstra)算法是单源最短路径算法,用于计算一个节点到其他节点的最短路径,与它类似的还有克鲁斯卡尔算法,是计算多源最短路径的,即每个节点到其他各节点的最短路径;
8.学习了关键路径长度, 其实是最远路径长度. 然而, 它并非最短路径的对偶问题. 我尝试修改 Dijkstra 算法来解决, 然后发现自己傻了.
9.计算关键路径需要用到拓扑排序,用正向拓扑计算关键路径上事件发生的最早时间,逆向拓扑计算最晚时间;
10.通过这段时间的学习,我对Java图这一模块有一定的了解,但随着学习内容的推进,Java程序代码越来越难理解,我会加强学习

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值