通过深度优先算法进行拓扑排序(Java)
package graph;
//拓扑排序用深度优先算法实现
import java.io.IOException;
import java.util.Scanner;
import java.util.Stack;
public class Topological
{
private class ENode
{
int ivex; // 该边所指向的顶点的位置
ENode nextEdge; // 指向下一条弧的指针
}
// 邻接表中表的顶点
private class VNode
{
int color;// 顶点颜色;
int d;// 初始时间戳;
int f;// 结束时间戳;
char data; // 顶点信息
ENode firstEdge; // 指向第一条依附该顶点的弧
VNode pre;
};
int time;
private VNode[] mVexs; // 顶点数组
/*
* 创建图(自己输入数据)
*/
public Topological()
{
// 输入"顶点数"和"边数"
System.out.printf("input vertex number: ");
int vlen = readInt();
System.out.printf("input edge number: ");
int elen = readInt();
if (vlen < 1 || elen < 1 || (elen > (vlen * (vlen - 1))))
{
System.out.printf("input error: invalid parameters!\n");
return;
}
// 初始化"顶点"
mVexs = new VNode[vlen];
for (int i = 0; i < mVexs.length; i++)
{
System.out.printf("vertex(%d): ", i);
mVexs[i] = new VNode();
mVexs[i].data = readChar();
mVexs[i].firstEdge = null;
}
// 初始化"边"
// mMatrix = new int[vlen][vlen];
for (int i = 0; i < elen; i++)
{
// 读取边的起始顶点和结束顶点
System.out.printf("edge(%d):", i);
char c1 = readChar();
char c2 = readChar();
int p1 = getPosition(c1);
int p2 = getPosition(c2);
// 初始化node1
ENode node1 = new ENode();
node1.ivex = p2;
// 将node1链接到"p1所在链表的末尾"
if (mVexs[p1].firstEdge == null)
mVexs[p1].firstEdge = node1;
else
linkLast(mVexs[p1].firstEdge, node1);
}
}
/*
* 创建图(输入有向图矩阵)
* 参数说明: vexs -- 顶点数组 edges -- 边数组
*/
public Topological(char[] vexs, char[][] edges)
{
// 初始化"顶点数"和"边数"
int vlen = vexs.length;
int elen = edges.length;
// 初始化"顶点"
mVexs = new VNode[vlen];
for (int i = 0; i < mVexs.length; i++)
{
mVexs[i] = new VNode();
mVexs[i].data = vexs[i];
mVexs[i].firstEdge = null;
}
// 初始化"边"
for (int i = 0; i < elen; i++)
{
// 读取边的起始顶点和结束顶点
char c1 = edges[i][0];
char c2 = edges[i][1];
// 读取边的起始顶点和结束顶点
int p1 = getPosition(edges[i][0]);
int p2 = getPosition(edges[i][1]);
// 初始化node1
ENode node1 = new ENode();
node1.ivex = p2;
// 将node1链接到"p1所在链表的末尾"
if (mVexs[p1].firstEdge == null)
mVexs[p1].firstEdge = node1;
else
linkLast(mVexs[p1].firstEdge, node1);
}
}
/*
* 将node节点链接到list的最后
*/
private void linkLast(ENode list, ENode node)
{
ENode p = list;
while (p.nextEdge != null)
p = p.nextEdge;
p.nextEdge = node;
}
/*
* 返回ch位置
*/
private int getPosition(char ch)
{
for (int i = 0; i < mVexs.length; i++)
if (mVexs[i].data == ch)
return i;
return -1;
}
/*
* 读取一个输入字符
*/
private char readChar()
{
char ch = '0';
do {
try
{
ch = (char) System.in.read();
} catch (IOException e)
{
e.printStackTrace();
}
} while (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')));
return ch;
}
/*
* 读取一个输入字符
*/
private int readInt()
{
Scanner scanner = new Scanner(System.in);
return scanner.nextInt();
}
/* 深度优先搜索遍历图的递归实现*/
Stack<Integer> stack = new Stack<Integer>();//辅助栈;
public void DFS_visit(int i, boolean[] visited)
{
ENode node;
// time= time+1;
mVexs[i].d = ++time;
mVexs[i].color = 0;// 1表示该节点颜色为灰色
visited[i] = true;
System.out.printf("%c(%d) ", mVexs[i].data,mVexs[i].d);//颜色
node = mVexs[i].firstEdge;
while (node != null)
{
if (mVexs[node.ivex].color == -1)
{
// System.out.println("("+i+","+node.ivex+")---树边");
DFS_visit(node.ivex, visited);
} else if (mVexs[node.ivex].color == 0)
{
System.out.println("(" + i + "," + node.ivex + ")---后向边,有环图,无拓扑排序");
}
// else
// {
// if(mVexs[i].color < mVexs[node.ivex].d)
// System.out.println("("+i+","+node.ivex+")---前向边");
// else if(mVexs[i].color > mVexs[node.ivex].d)
// System.out.println("("+i+","+node.ivex+")---横跨边");
// }
node = node.nextEdge;
}
mVexs[i].color = 1;
// time=time+1;
mVexs[i].f = ++time;
stack.push(i);
System.out.printf("%c(%d) ", mVexs[i].data,mVexs[i].f);
}
/*
* 深度优先搜索遍历图
*/
public void DFS()
{
time = 0;
boolean[] visited = new boolean[mVexs.length]; // 顶点访问标记
// 初始化所有顶点都没有被访问
for (int i = 0; i < mVexs.length; i++)
{
mVexs[i].color = -1;// 初始化所有顶点都为白色
mVexs[i].pre = null;
visited[i] = false;
}
System.out.printf("DFS: ");
for (int j = 0; j < mVexs.length; j++)
{
if (!visited[j])
DFS_visit(j, visited);
}
System.out.print("\n拓扑排序为:");
for (int i = 0; i < mVexs.length; i++)
{
System.out.print(mVexs[stack.pop()].data+" ");
}
}
/*
* 打印矩阵队列图
*/
public void print() {
System.out.printf("List Graph:\n");
for (int i = 0; i < mVexs.length; i++)
{
System.out.printf("%d(%c): ", i, mVexs[i].data);
ENode node = mVexs[i].firstEdge;
while (node != null)
{
System.out.printf("%d(%c) ", node.ivex, mVexs[node.ivex].data);
node = node.nextEdge;
}
System.out.printf("\n");
}
}
public static void main(String[] args) {
char[] vexs = { 'A', 'B', 'C', 'D', 'E', 'F', 'G' };
char[][] edges = new char[][] {
{ 'B', 'A' },
{ 'B', 'D' },
{ 'A', 'G' },
{ 'C', 'G' },
{ 'D', 'F' },
{ 'C', 'F' },
{ 'D', 'E' },};
Topological pG;
// 自定义"图"(输入矩阵队列)
// pG = new ListDG();
// 采用已有的"图"
pG = new Topological(vexs, edges);
pG.print(); // 打印图
pG.DFS(); // 深度优先遍
}
}