学习来源:日撸 Java 三百行(31-40天,图)_闵帆的博客——CSDN博客
一、整数矩阵及运算
算是对前面学习的矩阵内容的强化,涉及由二维数组构造矩阵、将矩阵元素存入二维数组、读写矩阵元素、矩阵相乘和相加等操作。
package JavaDay7;
import java.util.Arrays;
/**
* @author Kexiong Wang
*
* @date 2022年4月23日
*/
public class IntMatrix {
//二维数组存储矩阵
int[][] data;
/**
*********************
* 构造函数
*
* @param paraRows 行数
* @param paraColumns 列数
*********************
*/
public IntMatrix(int paraRows, int paraColumns) {
data = new int[paraRows][paraColumns];
}//Of IntMatrix
/**
*********************
* 构造函数
*
* @param paraMatrix 给定二维数组
*********************
*/
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];
}//Of for j
}//Of for i
}//Of IntMatrix
/**
*********************
* 构造函数
*
* @param paraMatrix 给定矩阵
*********************
*/
public IntMatrix(IntMatrix paraMatrix) {
this(paraMatrix.getData());
}//Of IntMatrix
/**
*********************
* 单位矩阵
*
* @param paraRows 矩阵行/列数
*********************
*/
public static IntMatrix getIdentityMatrix(int paraRows) {
IntMatrix resultMatrix = new IntMatrix(paraRows, paraRows);
for (int i = 0; i < paraRows; i++) {
resultMatrix.data[i][i] = 1;
}//Of for i
return resultMatrix;
}//Of getIdentityMatrix
/**
*********************
* toString方法
*********************
*/
public String toString() {
return Arrays.deepToString(data);
}//Of toString
/**
*********************
* data的get方法
*
* @return 存储矩阵的二维数组
*********************
*/
public int[][] getData() {
return data;
}// Of getData
/**
*********************
* 行数的get方法
*
* @return 行数
*********************
*/
public int getRows() {
return data.length;
}//Of getRows
/**
*********************
* 列数的get方法
*
* @return 列数
*********************
*/
public int getColumns() {
return data[0].length;
}//Of getColumns
/**
*********************
* 设置矩阵元素的值
*
* @param paraRow 元素所在行
* @param paraColumn 元素所在列
* @param paraValue 元素值
*********************
*/
public void setValue(int paraRow, int paraColumn, int paraValue) {
data[paraRow][paraColumn] = paraValue;
}//Of setValue
/**
*********************
* 获得矩阵中元素的值
*
* @param paraRow 元素所在行
* @param paraColumn 元素所在列
*********************
*/
public int getValue(int paraRow, int paraColumn) {
return data[paraRow][paraColumn];
}//Of getValue
/**
*********************
* 将另一个矩阵和本矩阵相加
*
* @param paraMatrix 给定的另一矩阵
*********************
*/
public void add(IntMatrix paraMatrix) throws Exception {
//从另一矩阵取数据
int[][] tempData = paraMatrix.getData();
//验证是否为同型矩阵
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
//将矩阵相加
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
/**
*********************
* 两矩阵相加
*
* @param paraMatrix1 第一个矩阵
* @param paraMatrix2 第二个矩阵
* @return 结果矩阵
*********************
*/
public static IntMatrix add(IntMatrix paraMatrix1, IntMatrix paraMatrix2) throws Exception {
//拷贝矩阵一元素到结果矩阵
IntMatrix resultMatrix = new IntMatrix(paraMatrix1);
//相加
resultMatrix.add(paraMatrix2);
return resultMatrix;
}//Of add
/**
*********************
* 两矩阵相乘
*
* @param paraMatrix1 第一个矩阵
* @param paraMatrix2 第二个矩阵
* @return 结果矩阵
*********************
*/
public static IntMatrix multiply(IntMatrix paraMatrix1, IntMatrix paraMatrix2)
throws Exception {
//验证是否符合矩阵相乘的要求
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
//分配空间
int[][] resultData = new int[tempData1.length][tempData2[0].length];
//相乘
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
//构造结果矩阵
IntMatrix resultMatrix = new IntMatrix(resultData);
return resultMatrix;
}//Of multiply
/**
*********************
* 程序入口
*
* @param args 暂未使用
*********************
*/
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
运行结果
二、图
1. 图的定义
图由顶点集和边集组成,顶点集表示图中顶点的有限非空集,边集表示图中顶点之间的边的集合。
2. 图的连通性
在无向图中,若任意两个顶点之间都有路径存在,则称图是连通的。在有向图中,若任意两个顶点a,b之间有从a到b和从b到a的两条路径,则称图是连通的。
3. 图的广度优先遍历
类似于二叉树的层序遍历。首先访问起点a,由起点出发访问a的各个未访问的邻接顶点,再依次访问各邻接顶点的未被访问的邻接顶点知道所有顶点都被访问过。
4. 图的深度优先遍历
类似树的先序遍历。先访问图中某一起点a,然后由a出发,访问与a邻接且未被访问的任一顶点b,再访问b的任一未被访问顶点c直到所有顶点都被访问过。
5. 图的m着色问题
给定一个图G和m种不同的颜色,用这些颜色为图G的各顶点着色,每个顶点着一种颜色。求是否有一种着色法使G中相邻的两个顶点有不同的颜色。
代码如下
package JavaDay7;
import JavaDay5.CircleObjectQueue;
import JavaDay5.ObjectStack;
import java.util.Arrays;
/**
* @author Kexiong Wang
*
* @date 2022年4月23日
*/
public class Graph {
//邻接矩阵
IntMatrix connectivityMatrix;
/**
*********************
* 构造函数
*
* @param paraNumNodes 节点数
*********************
*/
public Graph(int paraNumNodes) {
connectivityMatrix = new IntMatrix(paraNumNodes, paraNumNodes);
}//Of Graph
/**
*********************
* 构造函数
*
* @param paraMatrix 存储矩阵元素的二维数组
*********************
*/
public Graph(int[][] paraMatrix) {
connectivityMatrix = new IntMatrix(paraMatrix);
}//Of Graph
/**
*********************
* toString方法
*********************
*/
public String toString() {
String resultString = "This is the connectivity matrix of the graph.\r\n"
+ connectivityMatrix;
return resultString;
}//Of toString
/**
*********************
* 检测图的连通性
*********************
*/
public boolean getConnectivity() throws Exception {
//初始化M^0
IntMatrix tempConnectivityMatrix = IntMatrix.getIdentityMatrix(connectivityMatrix.getData().length);
//初始化M^1
IntMatrix tempMultipliedMatrix = new IntMatrix(connectivityMatrix);
//求M^a
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
//检查连通性
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
/**
*********************
* 连通性单元测试
*********************
*/
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 ee) {
System.out.println(ee);
}//Of try.
System.out.println("Is the graph connected? " + tempConnected);
//有向图测试
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
/**
*********************
* 广度优先遍历
*
* @param paraStartIndex 出发的节点
* @return 访问顺序
*********************
*/
public String breadthFirstTraversal(int paraStartIndex) {
CircleObjectQueue tempQueue = new CircleObjectQueue();
String resultString = "";
int tempNumNodes = connectivityMatrix.getRows();
boolean[] tempVisitedArray = new boolean[tempNumNodes];
//初始化队列
//访问节点后入队
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;
}//Of if
//没有直接相连
if (connectivityMatrix.getData()[tempIndex][i] == 0) {
continue;
}//Of if
//访问后入队
tempVisitedArray[i] = true;
resultString += i;
tempQueue.enqueue(new Integer(i));
}//Of for i
tempInteger = (Integer)tempQueue.dequeue();
}//Of while
return resultString;
}//Of breadthFirstTraversal
/**
*********************
* 广度优先遍历单元测试
*********************
*/
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);
}//Of try.
System.out.println("The breadth first order of visit: " + tempSequence);
}//Of breadthFirstTraversalTest
/**
*********************
* 深度优先遍历
*
* @param paraStartIndex 出发点
* @return 访问序列
*********************
*/
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;
}//Of if
if (connectivityMatrix.getData()[tempIndex][i] == 0) {
continue;
}//Of if
tempVisitedArray[i] = true;
resultString += i;
tempStack.push(new Integer(i));
System.out.println("Push " + i);
tempNext = i;
break;
}//Of for i
if (tempNext == -1) {
tempInteger = (Integer) tempStack.pop();
System.out.println("Pop " + tempInteger);
if (tempStack.isEmpty()) {
break;
} else {
tempInteger = (Integer) tempStack.pop();
tempIndex = tempInteger.intValue();
tempStack.push(tempInteger);
}//Of if
} else {
tempIndex = tempNext;
}//Of if
}//Of while
return resultString;
}//Of depthFirstTraversal
/**
*********************
* 深度优先遍历单元测试
*********************
*/
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);
}//Of try.
System.out.println("The depth first order of visit: " + tempSequence);
}//Of depthFirstTraversalTest
/**
*********************
* 图着色
*
* @param paraNumColors 颜色数
*********************
*/
public void coloring(int paraNumColors) {
//初始化
int tempNumNodes = connectivityMatrix.getRows();
int[] tempColorScheme = new int[tempNumNodes];
Arrays.fill(tempColorScheme, -1);
coloring(paraNumColors, 0, tempColorScheme);
}//Of coloring
/**
*********************
* 图着色
*
* @param paraNumColors 颜色数量
* @param paraCurrentNumNodes 当前要着色顶点
* @param paraCurrentColoring 当前着色计划
*********************
*/
public void coloring(int paraNumColors, int paraCurrentNumNodes, int[] paraCurrentColoring) {
//初始化
int tempNumNodes = connectivityMatrix.getRows();
System.out.println("coloring: paraNumColors = " + paraNumColors + ", paraCurrentNumNodes = " + paraCurrentNumNodes + ", paraCurrentColoring" + Arrays.toString(paraCurrentColoring));
//找到一种着色法
if (paraCurrentNumNodes >= tempNumNodes) {
System.out.println("Find one:" + Arrays.toString(paraCurrentColoring));
return;
}//Of if
//尝试着色
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
/**
*********************
* 着色是否冲突,对比当前节点和已着色节点
*
* @param paraCurrentNumNodes 当前节点
* @param paraColoring 当前颜色
* @return 是否冲突
*********************
*/
public boolean colorConflict(int paraCurrentNumNodes, int[] paraColoring) {
for (int i = 0; i < paraCurrentNumNodes - 1; i++) {
//不相连
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
/**
*********************
* 着色单元测试
*********************
*/
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(3);
}// Of coloringTest
/**
*********************
* 程序入口
*
* @param args 暂未使用
*********************
*/
public static void main(String args[]) {
System.out.println("Hello!");
Graph tempGraph = new Graph(3);
System.out.println(tempGraph);
//连通性测试
getConnectivityTest();
//广度优先遍历测试
breadthFirstTraversalTest();
//深度优先遍历测试
depthFirstTraversalTest();
//图着色测试
coloringTest();
}//Of main
}//Of class Graph
连通性测试结果
广度优先遍历结果
深度优先遍历结果
图的着色问题运行结果(有多种着色方式,只展示一种)