拓扑排序只能用于无环图。
// 顶点
class Vertex3 {
char label;
boolean visited;
public Vertex3(char label) {
this.label = label;
visited = false;
}
}
public class Topo {
private final int maxVer = 20;// 最大顶点数
private int[][] adjMat;// 邻接矩阵
private Vertex3[] vertex;// 顶点数组
private int curVer;// 当前顶点数
public Topo() {
curVer = 0;
vertex = new Vertex3[maxVer];
adjMat = new int[maxVer][maxVer];
for (int i = 0; i < maxVer; i++)
for (int j = 0; j < maxVer; j++)
adjMat[i][j] = 0;
}
// 添加顶点
public void addVer(char label) {
vertex[curVer++] = new Vertex3(label);
}
// 添加有向边,不是双向
public void addAdj(int i, int j) {
if (i == j)
return;
adjMat[i][j] = 1;
}
public void displayVer(int index) {
System.out.print(vertex[index].label);
}
// 拓扑排序:只能用于有向无环图
// 先找到一个起始点,找后继点,“删除”起始点,循环进行。该方法效率低,不如直接删除点好吧。
public void topo() {
int temp = curVer;
while (temp > 0) {
int first = findFirst();
if (first == -1) {
System.out.println("\nloop(s) occur");
return;
}
displayVer(first);
vertex[first].visited = true;
temp--;
}
for(int i=0;i<curVer;i++)
vertex[i].visited=false;
}
//找到一个点,没有其他点指向它或指向它的点都访问过了,说明该点是找到的一个新起点
private int findFirst() {
a: for (int i = 0; i < curVer; i++) {
for (int j = 0; j < curVer; j++) {
if (adjMat[j][i] == 1 && vertex[j].visited == false)
continue a;
}
if (vertex[i].visited == false)// 不取重复值
return i;
}
return -1;// 说明有环,没有环的单向图是一定有起始点的
}
public static void main(String[] args) {
Topo g = new Topo();
g.addVer('A');
g.addVer('B');
g.addVer('C');
g.addVer('D');
g.addAdj(0, 1);
g.addAdj(0, 2);
g.addAdj(1, 2);
g.addAdj(2, 3);
g.addAdj(3, 1);
g.topo();
}
}
//书上拓扑排序代码
// 顶点
class Vertex_1 {
char label;
public Vertex_1(char label) {
this.label = label;
}
}
public class Graph_2 {
char[] sortedArray;
private final int maxVer = 20;// 最大顶点数
private int[][] adjMat;// 邻接矩阵
private Vertex_1[] vertex;// 顶点数组
private int curVer;// 当前顶点数
public Graph_2() {
sortedArray = new char[maxVer];
curVer = 0;
vertex = new Vertex_1[maxVer];
adjMat = new int[maxVer][maxVer];
for (int i = 0; i < maxVer; i++)
for (int j = 0; j < maxVer; j++)
adjMat[i][j] = 0;
}
// 添加顶点
public void addVer(char label) {
vertex[curVer++] = new Vertex_1(label);
}
// 添加有向边
public void addAdj(int i, int j) {
if (i == j)
return;
adjMat[i][j] = 1;
}
public void displayVer(int index) {
System.out.print(vertex[index].label);
}
// 拓扑排序:只能用于有向无环图
// 先找到一个起始点,找后继点,删除起始点,循环进行
public void topo() {
int temp = curVer;
while (curVer > 0) {
int first = noSuccessors();
if (first == -1) {
System.out.println("\n graph has cycles");
return;
}
sortedArray[curVer - 1] = vertex[first].label;// 将图的末端点从后往前放入数组
deleteVer(first);
}
for (int i = 0; i < temp; i++)
System.out.print(sortedArray[i]);
System.out.println();
}
// 2个操作:第一步将顶点删除,第二步以要删除点为开头和结尾的临接矩阵元素删除,即矩阵收缩一维(要用的变少了而已)
private void deleteVer(int index) {
if (index != curVer - 1) {
for (int j = index; j < curVer - 1; j++)
vertex[j] = vertex[j + 1];// 从要删除的位置开始左移
for (int row = index; row < curVer - 1; row++)
moveRowUp(row, curVer);
for (int col = index; col < curVer - 1; col++)
moveColLeft(col, curVer - 1);// 因为上一个循环的原因,此时可以少移动一列
}
curVer--;
}
private void moveColLeft(int col, int length) {
for (int row = 0; row < length; row++)
adjMat[row][col] = adjMat[row][col + 1];
}
private void moveRowUp(int row, int length) {
for (int col = 0; col < length; col++)
adjMat[row][col] = adjMat[row + 1][col];
}
// 返回没有后继点的顶点,即图的末端,插入数组时正好从数组后面开始放
private int noSuccessors() {
boolean isEdge;
for (int row = 0; row < curVer; row++) {
isEdge = false;
for (int col = 0; col < curVer; col++) {
if (adjMat[row][col] > 0) {
isEdge = true;
break;
}
}
if (!isEdge)
return row;
}
return -1;
}
//WarShall算法,将临接矩阵修改,不论一步或多步,只要一个顶点能到达另一个顶点,相应矩阵元素设为1
//如A到B,B到C,那么A到C为1
public void WarShall(){
for(int y=0;y<curVer;y++){//行
for(int x=0;x<curVer;x++){//列
if(adjMat[y][x]==1)
for(int z=0;z<curVer;z++){//z代表x那一列
if(adjMat[x][z]==1)
adjMat[y][z]=1;
}
else continue;
}
}
for(int i=0;i<curVer;i++){
for(int j=0;j<curVer;j++)
System.out.print(adjMat[i][j]+" ");
System.out.println();
}
}
public static void main(String[] args) {
Graph_2 g = new Graph_2();
g.addVer('A');
g.addVer('B');
g.addVer('C');
g.addVer('D');
g.addVer('E');
g.addVer('F');
g.addVer('G');
g.addVer('H');
g.addAdj(0, 3);
g.addAdj(0, 4);
g.addAdj(1, 4);
g.addAdj(2, 5);
g.addAdj(3, 6);
g.addAdj(4, 6);
g.addAdj(5, 7);
g.addAdj(6, 7);
//g.topo();// BAEDGCFH
g.WarShall();//对拓扑排序好像无影响
g.topo();// BAEDGCFH
}
}