31-40 day

Day31:整数矩阵及其运算


import java.util.Arrays;

public class IntMatrix {
	
	//数据
	int[][] data;

	//构造函数
	public IntMatrix(int paraRows, int paraColumns) {
		data = new int[paraRows][paraColumns];
	}
	//第二个构造函数
	public IntMatrix(int[][] paraMatrix) {
		data = new int[paraMatrix.length][paraMatrix[0].length];

		
		for (int i = 0; i < data.length; i++) {
			for (int j = 0; j < data[0].length; j++) {
				data[i][j] = paraMatrix[i][j];
			} 
		} 
	}
	//第三个构造函数
	public IntMatrix(IntMatrix paraMatrix) {
		this(paraMatrix.getData());
	}

	//获取单位矩阵
	public static IntMatrix getIdentityMatrix(int paraRows) {
		IntMatrix resultMatrix = new IntMatrix(paraRows, paraRows);
		for (int i = 0; i < paraRows; i++) {
			
			resultMatrix.data[i][i] = 1;
		} 
		return resultMatrix;
	}


	public String toString() {
		return Arrays.deepToString(data);
	}

	//获取数据
	public int[][] getData() {
		return data;
	}

	//获取矩阵行
	public int getRows() {
		return data.length;
	}

	//获取矩阵列
	public int getColumns() {
		return data[0].length;
	}

	//设置某个位置的值
	public void setValue(int paraRow, int paraColumn, int paraValue) {
		data[paraRow][paraColumn] = paraValue;
	}

	//获取某个位置的值
	public int getValue(int paraRow, int paraColumn) {
		return data[paraRow][paraColumn];
	}

	//矩阵相加
	public void add(IntMatrix paraMatrix) throws Exception {
		// Step 1. 获取目标矩阵的数据获取
		int[][] tempData = paraMatrix.getData();

		// Step 2. 比较矩阵大小是否匹配
		if (data.length != tempData.length) {
			throw new Exception("Cannot add matrices. Rows not match: " + data.length + " vs. "
					+ tempData.length + ".");
		} 
		if (data[0].length != tempData[0].length) {
			throw new Exception("Cannot add matrices. Rows not match: " + data[0].length + " vs. "
					+ tempData[0].length + ".");
		}

		// Step 3. 矩阵相加
		for (int i = 0; i < data.length; i++) {
			for (int j = 0; j < data[0].length; j++) {
				data[i][j] += tempData[i][j];
			} /
		} /
	}

	//两个矩阵相加
	public static IntMatrix add(IntMatrix paraMatrix1, IntMatrix paraMatrix2) throws Exception {
		// Step 1.复制第一个矩阵
		IntMatrix resultMatrix = new IntMatrix(paraMatrix1);

		// Step 2. 加上第二个矩阵
		resultMatrix.add(paraMatrix2);

		return resultMatrix;
	}

	//矩阵相乘
	public static IntMatrix multiply(IntMatrix paraMatrix1, IntMatrix paraMatrix2)
			throws Exception {
		// Step 1. 匹配矩阵大小
		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 + ".");
		} 

		// Step 2. 分配空间
		int[][] resultData = new int[tempData1.length][tempData2[0].length];

		// Step 3. 相乘
		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];
				} 
			} 
		} 

		// Step 4.构造目标函数
		IntMatrix resultMatrix = new IntMatrix(resultData);

		return resultMatrix;
	}

	
	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);
		} 
		System.out.println("The square matrix is: " + tempMatrix2);

		IntMatrix tempMatrix3 = new IntMatrix(tempMatrix2);
		try {
			tempMatrix3.add(tempMatrix1);
		} catch (Exception ee) {
			System.out.println(ee);
		} 
		System.out.println("The connectivity matrix is: " + tempMatrix3);
	}

}

Day32:图的连通性检测

令图的连通矩阵为 M ,M0=I 为单位矩阵。要知道图的连通性, 只需要计算 Ma​=M0+M1+⋯+Mn−1,其中 n 是节点个数。Ma中第 i 行第 j 列元素为 0 的话,  就表示从节点 i 到节点 j 不可达。

    package DataStructure.graph;

    import matrix.IntMatrix;

    public class Graph {

    //连通矩阵
    IntMatrix connectivityMatrix;


    // 第一个构造函数
    public Graph(int paraNumNodes) {
        connectivityMatrix = new IntMatrix(paraNumNodes, paraNumNodes);
    }

    // 第二个构造函数
    public Graph(int[][] paraMatrix) {
        connectivityMatrix = new IntMatrix(paraMatrix);
    }


    public String toString() {
        String resultString = "This is the connectivity matrix of the graph.\r\n"
                + connectivityMatrix;
        return resultString;
    }

    //判断连通性
    public boolean getConnectivity() throws Exception {
        // 初始化单位矩阵
        IntMatrix tempConnectivityMatrix = IntMatrix
                .getIdentityMatrix(connectivityMatrix.getData().length);

        // 初始化目标矩阵
        IntMatrix tempMultipliedMatrix = new IntMatrix(connectivityMatrix);

        // 计算矩阵
        for (int i = 0; i < connectivityMatrix.getData().length - 1; i++) {

            tempConnectivityMatrix.add(tempMultipliedMatrix);


            tempMultipliedMatrix = IntMatrix.multiply(tempMultipliedMatrix, connectivityMatrix);
        }

        // 判断连通性
        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;
                }
            }
        }

        return true;
    }


    public static void getConnectivityTest() {
        // 测试一个非连通图
        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 e) {
            System.out.println(e);
        }

        System.out.println("Is the graph connected? " + tempConnected);

        // 测试一个连通图
        tempGraph2.connectivityMatrix.setValue(1, 0, 0);

        tempConnected = false;
        try {
            tempConnected = tempGraph2.getConnectivity();
        } catch (Exception e) {
            System.out.println(e);
        }

        System.out.println("Is the graph connected? " + tempConnected);
    }


    public static void main(String args[]) {

        Graph tempGraph = new Graph(3);
        System.out.println(tempGraph);

        getConnectivityTest();
    }
}

 Day33:图的广度优先遍历

图的广度优先遍历与树的广度优先遍历类似,可以模仿着学习。

代码:

public String breadthFirstTraversal(int paraStartIndex) {
		CircleObjectQueue tempQueue = new CircleObjectQueue();
		String resultString = "";
		
		int tempNumNodes = connectivityMatrix.getRows();
		boolean[] tempVisitedArray = new boolean[tempNumNodes];
		
		tempVisitedArray[paraStartIndex] = true;
		
		//初始化队列
		tempVisitedArray[paraStartIndex] = true;
		resultString += paraStartIndex;
		tempQueue.enqueue(new Integer(paraStartIndex));
		
		//广度遍历
		int tempIndex;
		Integer tempInteger = (Integer)tempQueue.dequeue();
		while (tempInteger != null) {
			tempIndex = tempInteger.intValue();
					
			//未访问的相邻点入队
			for (int i = 0; i < tempNumNodes; i ++) {
				if (tempVisitedArray[i]) {
					continue; 
				}
				
				if (connectivityMatrix.getData()[tempIndex][i] == 0) {
					continue; 
				}
				
				
				tempVisitedArray[i] = true;
				resultString += i;
				tempQueue.enqueue(new Integer(i));
			}
			
			//取队首元素
			tempInteger = (Integer)tempQueue.dequeue();
		}
		
		return resultString;
	}
	
	
	public static void breadthFirstTraversalTest() {
		// 测试无向图
		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);
		} 

		System.out.println("The breadth first order of visit: " + tempSequence);
	}

	
	public static void main(String args[]) {
		System.out.println("Hello!");
		Graph tempGraph = new Graph(3);
		System.out.println(tempGraph);

		
		getConnectivityTest();
		
		breadthFirstTraversalTest();
	}

Day34: 图的深度优先遍历

   与二叉树的深度优先遍历类似; 又见 while (true), 循环的退出条件是栈为空;需要在前面 import ObjectStack 。

代码:

public String depthFirstTraversal(int paraStartIndex) {
		ObjectStack tempStack = new ObjectStack();
		String resultString = "";
		
		int tempNumNodes = connectivityMatrix.getRows();
		boolean[] tempVisitedArray = new boolean[tempNumNodes];
		
		//初始化栈
		tempVisitedArray[paraStartIndex] = true;
		resultString += paraStartIndex;
		tempStack.push(new Integer(paraStartIndex));
		System.out.println("Push " + paraStartIndex);
		System.out.println("Visited " + resultString);
		
		//访问剩余点
		int tempIndex = paraStartIndex;
		int tempNext;
		Integer tempInteger;
		while (true){
		//找到一个未访问的邻点
			tempNext = -1;
			for (int i = 0; i < tempNumNodes; i ++) {
				if (tempVisitedArray[i]) {
					continue; 
				}
				
				if (connectivityMatrix.getData()[tempIndex][i] == 0) {
					continue;
				}
				
				
				tempVisitedArray[i] = true;
				resultString += i;
				tempStack.push(new Integer(i));
				System.out.println("Push " + i);
				tempNext = i;
				
				
				break;
			}
			
			
			if (tempNext == -1) {
				//回溯未访问的邻点
				if (tempStack.isEmpty()) {
					break;
				}
				tempInteger = (Integer)tempStack.pop();
				System.out.println("Pop " + tempInteger);
				tempIndex = tempInteger.intValue();
			} else {
				tempIndex = tempNext;
			}
		}/
		
		return resultString;
	}
	
	
	public static void depthFirstTraversalTest() {
		// 测试一个无向图
		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);
		} 

		System.out.println("The depth first order of visit: " + tempSequence);
	}

	
	public static void main(String args[]) {
		System.out.println("Hello!");
		Graph tempGraph = new Graph(3);
		System.out.println(tempGraph);

		
		getConnectivityTest();
		
		breadthFirstTraversalTest();

		depthFirstTraversalTest();
	}

Day35:图的 m 着色问题

  向连通图G和m种不同的颜色。用这些颜色为图G的各顶点着色,每个顶点着一种颜色。是否有一种着色法使G中每条边的2个顶点着不同颜色。这个问题是图的m可着色判定问题。 

代码: 

package DataStructure.graph;

import DataStructure.LinkedList;
import DataStructure.queue.CircleObjectQueue;
import DataStructure.stack.ObjectStack;


public class NeighborList {

    class NeighborNode {
        //图序号
        int data;

        //下一节点
        NeighborNode next;


        public NeighborNode(int data) {
            this.data = data;
            next = null;
        }
    }

    //节点数量
    int numNodes;

    //每行的头节点
    NeighborNode[] headers;

    
    public NeighborList(int[][] paraMatrix) {
        numNodes = paraMatrix.length;

        NeighborNode tpNode;

        headers = new NeighborNode[numNodes];

        //链接上每个节点相邻接的节点
        for (int i = 0; i < numNodes; i++) {
            headers[i] = new NeighborNode(i);
            tpNode = headers[i];

            for (int j = 0; j < numNodes; j++) {
                if (paraMatrix[i][j] == 0) {
                    continue;
                }

                tpNode.next = new NeighborNode(j);
                tpNode = tpNode.next;
            }
        }
    }

    
    public String toString() {
        String resString = "NeighborList: \n";

        NeighborNode tpNode;

        for (int i = 0; i < numNodes; i++) {
            tpNode = headers[i];


            while (tpNode.next != null) {
                resString += tpNode.data + "->";
                tpNode = tpNode.next;
            }

            resString += tpNode.data + "\n";
        }
        return resString;
    }

   
    public String breadthFirstTraversal(int paraStartIndex) {
        CircleObjectQueue tpQueue = new CircleObjectQueue();
        String resString = "";

        boolean[] tpVisitedArray = new boolean[numNodes];

        tpVisitedArray[paraStartIndex] = true;
        resString += paraStartIndex;
        tpQueue.enqueue(paraStartIndex);

        //利用节点去遍历
        int tpIndex;
        Integer tempInteger = (Integer) tpQueue.dequeue();
        NeighborNode tpNode;
        while (tempInteger != null) {
            tpIndex = tempInteger.intValue();

            tpNode = headers[tpIndex];

            while (tpNode.next != null) {
                tpNode = tpNode.next;
                if (tpVisitedArray[tpNode.data]) {
                    continue;
                }
                tpQueue.enqueue(tpNode.data);
                tpVisitedArray[tpNode.data] = true;
                resString += tpNode.data;
            }

            tempInteger = (Integer) tpQueue.dequeue();
        }
        return resString;
    }
    //广度优先遍历
    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}};
        NeighborList tpNeighborList = new NeighborList(tempMatrix);
        System.out.println(tpNeighborList);

        String tempSequence = "";
        try {
            tempSequence = tpNeighborList.breadthFirstTraversal(2);
        } catch (Exception e) {
            System.out.println(e);
        }

        System.out.println("The breadth first order of visit: " + tempSequence);
    }


      //深度优先遍历
         public String depthFirstTraversal(int paraStartIndex) {
        ObjectStack tpStack = new ObjectStack();
        String resString = "";

        boolean[] tpVisitedArray = new boolean[numNodes];

        tpVisitedArray[paraStartIndex] = true;

        NeighborNode tpNode = headers[paraStartIndex];
        ;

        resString += paraStartIndex;

        tpStack.push(tpNode);

        int num = 1;
        while (num < numNodes) {

            while (tpNode.next != null && tpVisitedArray[tpNode.next.data]) {
                tpNode = tpNode.next;
            }

            //回溯
            if (tpNode.next == null) {
                tpNode = (NeighborNode) tpStack.pop();
                continue;
            }


            resString += tpNode.next.data;
            tpStack.push(tpNode.next);
            tpVisitedArray[tpNode.next.data] = true;
            tpNode = headers[tpNode.next.data];
            num++;
        }
        return resString;
    }

    // 深度优先遍历测试
    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}};
        NeighborList tpNeighborList = new NeighborList(tempMatrix);
        System.out.println(tpNeighborList);

        String tempSequence = "";
        try {
            tempSequence = tpNeighborList.depthFirstTraversal(0);
        } catch (Exception ee) {
            System.out.println(ee);
        }

        System.out.println("The depth first order of visit: " + tempSequence);
    }

    public static void main(String[] args) {
        int[][] tempMatrix = {{0, 1, 0, 0}, {0, 0, 0, 1}, {1, 0, 0, 0}, {0, 1, 1, 0}};
        NeighborList tpList = new NeighborList(tempMatrix);
        System.out.println(tpList);


        breadthFirstTraversalTest();

        depthFirstTraversalTest();
    }
}

Day36: 邻连表

  相当于图的压缩存储. 每一行数据用一个单链表存储。重写了广度优先遍历。可以发现, 使用队列的机制不变.。仅仅是把其中的 for 循环换成了 while, 避免检查不存在的边.。如果图很稀疏的话, 可以降低时间复杂度。

代码:

package DataStructure.graph;

import DataStructure.LinkedList;
import DataStructure.queue.CircleObjectQueue;
import DataStructure.stack.ObjectStack;


public class NeighborList {

    class NeighborNode {
        //图序号
        int data;

        //下一节点
        NeighborNode next;


        public NeighborNode(int data) {
            this.data = data;
            next = null;
        }
    }

    //节点数量
    int numNodes;

    //每行的头节点
    NeighborNode[] headers;

    
	//构造函数
    public NeighborList(int[][] paraMatrix) {
        numNodes = paraMatrix.length;

        NeighborNode tpNode;

        headers = new NeighborNode[numNodes];

        //链接上每个节点相邻接的节点
        for (int i = 0; i < numNodes; i++) {
            headers[i] = new NeighborNode(i);
            tpNode = headers[i];

            for (int j = 0; j < numNodes; j++) {
                if (paraMatrix[i][j] == 0) {
                    continue;
                }

                tpNode.next = new NeighborNode(j);
                tpNode = tpNode.next;
            }
        }
    }

    @Override
    public String toString() {
        String resString = "NeighborList: \n";

        NeighborNode tpNode;

        for (int i = 0; i < numNodes; i++) {
            tpNode = headers[i];


            while (tpNode.next != null) {
                resString += tpNode.data + "->";
                tpNode = tpNode.next;
            }

            resString += tpNode.data + "\n";
        }
        return resString;
    }

    //广度优先遍历
    public String breadthFirstTraversal(int paraStartIndex) {
        CircleObjectQueue tpQueue = new CircleObjectQueue();
        String resString = "";

        boolean[] tpVisitedArray = new boolean[numNodes];

        tpVisitedArray[paraStartIndex] = true;
        resString += paraStartIndex;
        tpQueue.enqueue(paraStartIndex);

        //根据节点去遍历
        int tpIndex;
        Integer tempInteger = (Integer) tpQueue.dequeue();
        NeighborNode tpNode;
        while (tempInteger != null) {
            tpIndex = tempInteger.intValue();

            tpNode = headers[tpIndex];

            while (tpNode.next != null) {
                tpNode = tpNode.next;
                if (tpVisitedArray[tpNode.data]) {
                    continue;
                }
                tpQueue.enqueue(tpNode.data);
                tpVisitedArray[tpNode.data] = true;
                resString += tpNode.data;
            }

            tempInteger = (Integer) tpQueue.dequeue();
        }
        return resString;
    }

    // 广度优先遍历测试
    public static void breadthFirstTraversalTest() {
        //测试无向图
        int[][] tempMatrix = {{0, 1, 1, 0}, {1, 0, 0, 1}, {1, 0, 0, 1}, {0, 1, 1, 0}};
        NeighborList tpNeighborList = new NeighborList(tempMatrix);
        System.out.println(tpNeighborList);

        String tempSequence = "";
        try {
            tempSequence = tpNeighborList.breadthFirstTraversal(2);
        } catch (Exception e) {
            System.out.println(e);
        }

        System.out.println("The breadth first order of visit: " + tempSequence);
    }


    //深度优先遍历
    public String depthFirstTraversal(int paraStartIndex) {
        ObjectStack tpStack = new ObjectStack();
        String resString = "";

        boolean[] tpVisitedArray = new boolean[numNodes];

        tpVisitedArray[paraStartIndex] = true;

        NeighborNode tpNode = headers[paraStartIndex];
        ;

        resString += paraStartIndex;

        tpStack.push(tpNode);

        int num = 1;
        while (num < numNodes) {

            while (tpNode.next != null && tpVisitedArray[tpNode.next.data]) {
                tpNode = tpNode.next;
            }

            //回溯
            if (tpNode.next == null) {
                tpNode = (NeighborNode) tpStack.pop();
                continue;
            }


            resString += tpNode.next.data;
            tpStack.push(tpNode.next);
            tpVisitedArray[tpNode.next.data] = true;
            tpNode = headers[tpNode.next.data];
            num++;
        }
        return resString;
    }

    //深度优先遍历测试
    public static void depthFirstTraversalTest() {
        //测试无向图
        int[][] tempMatrix = {{0, 1, 1, 0}, {1, 0, 0, 1}, {1, 0, 0, 0}, {0, 1, 0, 0}};
        NeighborList tpNeighborList = new NeighborList(tempMatrix);
        System.out.println(tpNeighborList);

        String tempSequence = "";
        try {
            tempSequence = tpNeighborList.depthFirstTraversal(0);
        } catch (Exception ee) {
            System.out.println(ee);
        }

        System.out.println("The depth first order of visit: " + tempSequence);
    }

    public static void main(String[] args) {
        int[][] tempMatrix = {{0, 1, 0, 0}, {0, 0, 0, 1}, {1, 0, 0, 0}, {0, 1, 1, 0}};
        NeighborList tpList = new NeighborList(tempMatrix);
        System.out.println(tpList);


        breadthFirstTraversalTest();

        depthFirstTraversalTest();
    }
}

Day37:十字链表

  十字链表是为了便于求得图中顶点的度(出度和入度)而提出来的。它是综合邻接表和逆邻接表形式的一种链式存储结构。

  在十字链表存储结构中,有向图中的顶点的结构如下所示:

  其中data表示顶点的具体数据信息,而firstIn则表示指向以该顶点为弧头的第一个弧节点。而firstOut则表示指向以该顶点为弧尾的第一个弧节点。

代码:

package datastructure.graph;

public class OrthogonalList {

	
	class OrthogonalNode {
		
		//行数
		int row;

		//列数
		int column;

		//出节点
		OrthogonalNode nextOut;

		//入节点
		OrthogonalNode nextIn;

		
		public OrthogonalNode(int paraRow, int paraColumn) {
			row = paraRow;
			column = paraColumn;
			nextOut = null;
			nextIn = null;
		}
	}

	//节点数
	int numNodes;

	//每行的初始节点
	OrthogonalNode[] headers;

	
	public OrthogonalList(int[][] paraMatrix) {
		numNodes = paraMatrix.length;

		// Step 1. 初始化
		OrthogonalNode tempPreviousNode, tempNode;

		headers = new OrthogonalNode[numNodes];

		// Step 2. 链接出节点
		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;
				} 

			
				tempNode = new OrthogonalNode(i, j);

			
				tempPreviousNode.nextOut = tempNode;
				tempPreviousNode = tempNode;
			} 
		} 

		// Step 3. 链接入节点
		OrthogonalNode[] tempColumnNodes = new OrthogonalNode[numNodes];
		for (int i = 0; i < numNodes; i++) {
			tempColumnNodes[i] = headers[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;
			} 
		} 
	}

	
	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;
			}
			resultString += "\r\n";
		} 

		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;
			} 
			resultString += "\r\n";
		} 

		return resultString;
	}
	
	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);
	}
}

Day38: Dijkstra 算法与 Prim 算法

迪杰斯特拉算法(Dijkstra算法)是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。

普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树。意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点,且其所有边的权值之和亦为最小。

代码:

package datastructure.graph;

import java.util.Arrays;

import matrix.IntMatrix;


public class Net {

	//最大距离
	public static final int MAX_DISTANCE = 10000;

	//节点数
	int numNodes;

	//权重矩阵
	IntMatrix weightMatrix;

	
	public Net(int paraNumNodes) {
		numNodes = paraNumNodes;
		weightMatrix = new IntMatrix(numNodes, numNodes);
		for (int i = 0; i < numNodes; i++) {
			
			Arrays.fill(weightMatrix.getData()[i], MAX_DISTANCE);
		} 
	}


	public Net(int[][] paraMatrix) {
		weightMatrix = new IntMatrix(paraMatrix);
		numNodes = weightMatrix.getRows();
	}

	public String toString() {
		String resultString = "This is the weight matrix of the graph.\r\n" + weightMatrix;
		return resultString;
	}
	
	//The Dijkstra 算法: 目标节点到每个节点的最短路径.
	public int[] dijkstra(int paraSource) {
		// Step 1. 初始化
		int[] tempDistanceArray = new int[numNodes];
		for (int i = 0; i < numNodes; i++) {
			tempDistanceArray[i] = weightMatrix.getValue(paraSource, i);
		} 

		int[] tempParentArray = new int[numNodes];
		Arrays.fill(tempParentArray, paraSource);
		// -1 表示无父节点
		tempParentArray[paraSource] = -1;

		// 以访问的节点跳过
		boolean[] tempVisitedArray = new boolean[numNodes];
		tempVisitedArray[paraSource] = true;

		// Step 2. 主循环
		int tempMinDistance;
		int tempBestNode = -1;
		for (int i = 0; i < numNodes - 1; i++) {
			// Step 2.1 找出一个最佳节点
			tempMinDistance = Integer.MAX_VALUE;
			for (int j = 0; j < numNodes; j++) {
				// 这个节点被访问.
				if (tempVisitedArray[j]) {
					continue;
				} 

				if (tempMinDistance > tempDistanceArray[j]) {
					tempMinDistance = tempDistanceArray[j];
					tempBestNode = j;
				} 
			} 

			tempVisitedArray[tempBestNode] = true;

			// Step 2.2 准备下一轮
			for (int j = 0; j < numNodes; j++) {
				// 节点被访问
				if (tempVisitedArray[j]) {
					continue;
				} 

				// 节点不能到达
				if (weightMatrix.getValue(tempBestNode, j) >= MAX_DISTANCE) {
					continue;
				} /

				if (tempDistanceArray[j] > tempDistanceArray[tempBestNode]
						+ weightMatrix.getValue(tempBestNode, j)) {
					// 修改距离
					tempDistanceArray[j] = tempDistanceArray[tempBestNode]
							+ weightMatrix.getValue(tempBestNode, j);
					// 修改父节点
					tempParentArray[j] = tempBestNode;
				} 
			} 

			//测试
			System.out.println("The distance to each node: " + Arrays.toString(tempDistanceArray));
			System.out.println("The parent of each node: " + Arrays.toString(tempParentArray));
		} 

		// Step 3. 输出
		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;
	}
	
	//普利姆算法
	public int prim() {
		// Step 1. 初始化
		//任何节点都可以作为起始节点
		int tempSource = 0;
		int[] tempDistanceArray = new int[numNodes];
		for (int i = 0; i < numNodes; i++) {
			tempDistanceArray[i] = weightMatrix.getValue(tempSource, i);
		} 

		int[] tempParentArray = new int[numNodes];
		Arrays.fill(tempParentArray, tempSource);
	
		tempParentArray[tempSource] = -1;

		
		boolean[] tempVisitedArray = new boolean[numNodes];
		tempVisitedArray[tempSource] = true;

		// Step 2. 主循环
		int tempMinDistance;
		int tempBestNode = -1;
		for (int i = 0; i < numNodes - 1; i++) {
			// Step 2.1 找出一个最佳节点
			tempMinDistance = Integer.MAX_VALUE;
			for (int j = 0; j < numNodes; j++) {
				// 这个节点被访问.
				if (tempVisitedArray[j]) {
					continue;
				} 

				if (tempMinDistance > tempDistanceArray[j]) {
					tempMinDistance = tempDistanceArray[j];
					tempBestNode = j;
				} 
			} 

			tempVisitedArray[tempBestNode] = true;

			// Step 2.2 准备下一轮
			for (int j = 0; j < numNodes; j++) {
				// 节点被访问
				if (tempVisitedArray[j]) {
					continue;
				} 

				// 节点不能到达
				if (weightMatrix.getValue(tempBestNode, j) >= MAX_DISTANCE) {
					continue;
				} 

				// Attention: the difference from the Dijkstra algorithm.
				if (tempDistanceArray[j] > weightMatrix.getValue(tempBestNode, j)) {
					// 改变距离
					tempDistanceArray[j] = weightMatrix.getValue(tempBestNode, j);
					// 改变父节点
					tempParentArray[j] = tempBestNode;
				} 
			} 

			// 测试
			System.out.println(
					"The selected distance for each node: " + Arrays.toString(tempDistanceArray));
			System.out.println("The parent of each node: " + Arrays.toString(tempParentArray));
		} 

		int resultCost = 0;
		for (int i = 0; i < numNodes; i++) {
			resultCost += tempDistanceArray[i];
		} 
		// Step 3. 输出
		System.out.println("Finally");
		System.out.println("The parent of each node: " + Arrays.toString(tempParentArray));
		System.out.println("The total cost: " + resultCost);

		return resultCost;
	}

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

		
		tempNet1.dijkstra(1);

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

Day39: 关键路径

拓扑排序(Topological Sorting)是一个有向无环图的所有顶点的线性序列。且该序列必须满足下面两个条件:每个顶点出现且只出现一次。;若存在一条从顶点 A 到顶点 B 的路径,那么在序列中顶点 A 出现在顶点 B 的前面。

关键路径是指设计中从输入到输出经过的延时最长的逻辑路径。

代码:

	//关键路径
	public boolean[] criticalPath() {
		
		int tempValue;

		// Step 1. 存储每个节点的度数
		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]++;
				} /
			} 
		} 
		System.out.println("In-degree of nodes: " + Arrays.toString(tempInDegrees));

		// Step 2. 拓扑排序
		int[] tempEarliestTimeArray = new int[numNodes];
		for (int i = 0; i < numNodes; i++) {
			// 该节点不能移除
			if (tempInDegrees[i] > 0) {
				continue;
			} 

			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;
					} 
					tempInDegrees[j]--;
				} 
			} 
		} 

		System.out.println("Earlest start time: " + Arrays.toString(tempEarliestTimeArray));

		// Step 3. 每个节点的出度
		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]++;
				} 
			} 
		} 
		System.out.println("Out-degree of nodes: " + Arrays.toString(tempOutDegrees));

		// Step 4. 逆向拓扑排序
		int[] tempLatestTimeArray = new int[numNodes];
		for (int i = 0; i < numNodes; i++) {
			tempLatestTimeArray[i] = tempEarliestTimeArray[numNodes - 1];
		} 

		for (int i = numNodes - 1; i >= 0; i--) {
			// 该节点不能移除
			if (tempOutDegrees[i] > 0) {
				continue;
			} 

			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;
					} 
					tempOutDegrees[j]--;
					System.out.println("The out-degree of " + j + " decreases by 1.");
				} 
			} 
		} 

		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;
			} 
		} 
		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);
			} 
		} 
		System.out.println();

		return resultCriticalArray;
	}
	
	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);

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

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

Day 40:小结

1.复习了矩阵的创建与运算,学习了Exception 的抛出与捕获机制;利用 this 调用其它的构造方法可以减少冗余代码。

2.通过实际操作体会到矩阵在图的算法中的重要作用。

3.图的联通性问题可以用矩阵解决。

4.图的广度优先遍历和深度优先遍历与树的类似,可以对比理解学习。

5.通过学习图的 m 着色问题学会了回溯算法。

6.十字链表只能表示有向图。

7.邻接表既可以表示有向图又可以表示无向图。

8.学写了Dijkstra 算法和 Prim 算法,Dijkstra 算法需要有向图;Prim 算法需要无向图。

9.在编写关键路径时,拓扑排序发挥重要作用。

10.代码越来越多,需要加强应用和理解。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值