通过深度优先算法进行拓扑排序(算法导论)

通过深度优先算法进行拓扑排序(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 stack = new Stack();//辅助栈;
	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(); // 深度优先遍
	}

}

你可能感兴趣的:(算法导论)