三、拓扑排序
(一)、定义
- 拓扑排序: Topological Sort,函数命名:topoSort
- AOV-网: 有向无环网,顶点活动网。
- 用法: 用于判断有向图中死否存在回路(或环)。
- 若图中所有顶点都在拓扑排序的序列中,则图一定无环。
- 实际意义:
- 例如,假定一个计算机专业的学生必须完成图3-4所列出的全部课程。在这里,课程代表活动,学习一门课程就表示进行一项活动,学习每门课程的先决条件是学完它的全部先修课程。如学习《数据结构》课程就必须安排在学完它的两门先修课程《离散数学》和《算法语言》之后。学习《高等数学》课程则可以随时安排,因为它是基础课程,没有先修课。若用AOV网来表示这种课程安排的先后关系,则如图3-5所示。图中的每个顶点代表一门课程,每条有向边代表起点对应的课程是终点对应课程的先修课。从图中可以清楚地看出各课程之间的先修和后续的关系。如课程C5的先修课为C2,后续课程为C4和C6。
- 算法:
- 找一个入读为0的顶点
- 删除该顶点和以该顶点为起点的边
- 重复 1, 2
(二)、Java代码
1. 更新MGraph.java文件
package graph;
interface IGraph {
public int getVexNum();
public int getArcNum();
public int indexOfVex(String data);
public String valueOfVex(int index);
public void printMGraph();
}
public class MGraph implements IGraph {
public static final int INF = 99;
String[] vexs;
int[][] arcs;
int vexNum;
int arcNum;
public MGraph(String[] vertexs, int[][] adjMatrix) {
int num = vertexs.length;
int row = adjMatrix.length;
int col = adjMatrix[0].length;
if (row != col && row != num) {
throw new RuntimeException("row != col,邻接矩阵有误!");
}
vexNum = num;
vexs = new String[vexNum];
arcs = new int[vexNum][vexNum];
for (int i = 0; i < vexNum; i++) {
vexs[i] = vertexs[i];
}
for (int i = 0; i < vexNum; i++) {
for (int j = 0; j < vexNum; j++) {
arcs[i][j] = adjMatrix[i][j];
}
}
for (int i = 0; i < vexNum; i++) {
for (int j = 0; j < vexNum; j++) {
if (arcs[i][j] != 0 && arcs[i][j] != INF) {
arcNum++;
}
}
}
}
@Override
public int getVexNum() {
return this.vexNum;
}
@Override
public int getArcNum() {
return this.arcNum;
}
@Override
public int indexOfVex(String data) {
for (int i = 0; i < vexNum; i++) {
if (vexs[i] == data)
return i;
}
return -1;
}
@Override
public String valueOfVex(int index) {
if (index < 0 || index >= vexNum) {
throw new RuntimeException("位置错误!");
}
return vexs[index];
}
@Override
public void printMGraph() {
System.out.println("邻接矩阵:");
int t = 0;
for (int i = 0; i < arcs.length; i++) {
for (int j = 0; j < arcs.length; j++) {
System.out.printf("%3d", arcs[i][j]);
t++;
if (t % arcs.length == 0) {
System.out.println();
}
}
}
}
}
2. topoSort算法
package graph;
public class GraphApp extends MGraph {
public GraphApp(String[] vertexs, int[][] adjMatrix) {
super(vertexs, adjMatrix);
}
public int[] getIndegrees() {
int[] indegrees = new int[vexNum];
for (int i = 0; i < vexNum; i++) {
int count = 0;
for (int j = 0; j < vexNum; j++) {
if (arcs[j][i] == 1) {
count++;
}
}
indegrees[i] = count;
}
return indegrees;
}
public void topoSort() {
int[] indegrees = getIndegrees();
String[] topos = new String[vexNum];
int count = 0;
boolean flag = true;
while (flag) {
for (int i = 0; i < vexNum; i++) {
if (indegrees[i] == 0) {
topos[count++] = vexs[i];
indegrees[i] = -1;
for (int j = 0; j < vexNum; j++) {
if (arcs[i][j] == 1)
indegrees[j] -= 1;
}
}
}
if (count == vexNum) {
flag = false;
}
}
System.out.println("给出图的拓扑排序结果:");
for (int i = 0; i < vexNum; i++) {
System.out.print(topos[i] + "\t");
}
System.out.println();
}
public static void main(String[] args) {
System.out.println("《测试拓扑排序》");
String[] vertexs = { "v1", "v2", "v3", "v4", "v5", "v6" };
int[][] adjMatrix = { { 0, 1, 1, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0 }, { 0, 1, 0, 0, 1, 0 }, { 0, 0, 0, 0, 1, 0 },
{ 0, 0, 0, 0, 0, 0 }, { 0, 0, 0, 1, 1, 0 } };
GraphApp DG = new GraphApp(vertexs, adjMatrix);
DG.printMGraph();
int[] indegrees = DG.getIndegrees();
System.out.println("给出图的所有节点(按照字母顺序排列)的入度值:");
for (int i = 0; i < indegrees.length; i++)
System.out.print(indegrees[i] + "\t");
System.out.println();
DG.topoSort();
}
}
(三)、输出样例
(三)、输出样例
四、最短路径
(一)、Java代码
1. dijkstra
package graph;
public class GraphApp extends MGraph {
public GraphApp(String[] vertexs, int[][] adjMatrix) {
super(vertexs, adjMatrix);
}
public int[] dijkstra(int start) {
int length = vexNum;
for (int i = 0; i < vexNum; i++) {
for (int j = 0; j < vexNum; j++) {
if (arcs[i][j] == 0) {
arcs[i][j] = INF;
}
if (i == j) {
arcs[i][j] = 0;
}
}
}
int[] dijkstras = new int[length];
dijkstras[start] = 0;
String shortPath[] = new String[length];
for (int i = 0; i < length; i++) {
shortPath[i] = start + "->" + i;
}
boolean visited[] = new boolean[length];
visited[start] = true;
for (int count = 1; count < length; count++) {
int index = -1;
int minDistance = Integer.MAX_VALUE;
for (int i = 0; i < length; i++) {
if (visited[i] == false && arcs[start][i] < minDistance) {
minDistance = arcs[start][i];
index = i;
}
}
dijkstras[index] = minDistance;
visited[index] = true;
for (int i = 0; i < length; i++) {
if (visited[i] == false && arcs[start][index] + arcs[index][i] < arcs[start][i]) {
arcs[start][i] = arcs[start][index] + arcs[index][i];
shortPath[i] = shortPath[index] + "->" + i;
}
}
}
for (int i = 0; i < length; i++) {
System.out.println(shortPath[i] + " = " + dijkstras[i]);
}
return dijkstras;
}
public static void main(String[] args) {
String[] vertexs = { "v0", "v1", "v2", "v3", "v4", "v5" };
int[][] adjMatrix = { { 0, 0, 10, 0, 30, 100 }, { 0, 0, 5, 0, 0, 0, 0 }, { 0, 0, 0, 50, 0, 0 },
{ 0, 0, 0, 0, 0, 10 }, { 0, 0, 0, 20, 0, 60 }, { 0, 0, 0, 0, 0, 0 } };
Test test = new Test(vertexs, adjMatrix);
test.printMGraph();
test.dijkstra(0);
}
}
(二)、输出样例