最小生成树只需要在dfs基础上稍做修改,用最少的边连接所有可连接的顶点(无重复)。
拓扑排序只能用于无环图。
class Stack {
private int[] st;
private final int size = 20;
private int top;
public Stack() {
st = new int[size];
top = -1;
}
public void push(int j) {
st[++top] = j;
}
public int pop() {
return st[top--];
}
public int peek() {
return st[top];
}
public boolean isEmpty() {
return top == -1;
}
}
// 顶点
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;// 当前顶点数
private Stack stack;
public Topo() {
curVer = 0;
stack = new Stack();
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);
}
// 最小生成树,用最少的边连接所有可连接的顶点(无重复)
// 在dfs基础上稍作修改即可
public void mst(int index) {
vertex[index].visited = true;
stack.push(index);
int k;
while (!stack.isEmpty()) {
int cur = stack.peek();
k = findUnvisitedAdj(cur);
if (k == -1)
stack.pop();
else {
stack.push(k);
vertex[k].visited = true;
displayVer(cur);
displayVer(k);
System.out.print(" ");
}
}
// 搜索一次后重置访问状态,便于下次搜索
for (int i = 0; i < curVer; i++)
vertex[i].visited = false;
}
// 找到一个未访问过的相邻顶点
public int findUnvisitedAdj(int index) {
for (int i = 0; i < curVer; i++)
if (adjMat[index][i] == 1 && vertex[i].visited == false)
return i;
return -1;
}
// 拓扑排序:只能用于有向无环图
// 先找到一个起始点,找后继点,“删除”起始点,循环进行。该方法效率低,不如直接删除点好吧。
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.mst(1);
System.out.println();
g.topo();
}
}