【算法系列 三】 Quene

那年仲夏 提交于 2019-12-07 13:07:52

1. 拓扑排序问题(HDU 1285)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;

public class Main
{
	static int[] inDegree = new int[502];
	static int[][] v = new int[502][502];
	static boolean[] contain = new boolean[502];

	public static void main(String[] args) throws IOException
	{
		StreamTokenizer in = new StreamTokenizer(new BufferedReader(
				new InputStreamReader(System.in)));
		int n, m;
		while (in.nextToken() != StreamTokenizer.TT_EOF)
		{
			n = (int) in.nval;
			in.nextToken();
			m = (int) in.nval;
			init(n);
			for (int i = 1; i <= m; i++)
			{
				in.nextToken();
				int p1 = (int) in.nval;
				in.nextToken();
				int p2 = (int) in.nval;
				if(v[p1][p2] == 0)
				{
					inDegree[p2]++;
				}
				v[p1][p2] = 1;
			}
			topologicalOrder(n);
			System.out.println();
		}
	}

	private static void topologicalOrder(int n)
	{
		// TODO Auto-generated method stub
		int vv;
		for (int i = 1; i <= n; i++)
		{
			for (int j = 1; j <= n; j++)
			{
				if (inDegree[j] == 0 && contain[j])
				{
					vv = j;
					contain[vv] = false;
					for (int j2 = 1; j2 <= n; j2++)
					{
						if (v[vv][j2] > 0)
						{
							inDegree[j2]--;
						}
					}
					System.out.print(vv);
					if(i != n)
					{
						System.out.print(" ");
					}
					break;
				}
			}

		}

	}

	private static void init(int n)
	{
		// TODO Auto-generated method stub
		for (int i = 1; i <= n; i++)
		{
			for (int j = 1; j <= n; j++)
			{
				v[i][j] = 0;
			}
			inDegree[i] = 0;
			contain[i] = true;
		}

	}

}
上述代码就是最简单的拓扑排序,里面有很多可以优化的地方,比如用如果数据稀疏的话可以用邻接表来代替二维数组(矩阵),在找编号最小的且度为0的顶点,可以使用最小堆( 优先队列)。下面代码使用优先队列来代替原本的遍历查找,使复杂度降低。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.PriorityQueue;
import java.util.Queue;

public class Main
{
	static int[] inDegree = new int[502];
	static int[][] v = new int[502][502];

	public static void main(String[] args) throws IOException
	{
		StreamTokenizer in = new StreamTokenizer(new BufferedReader(
				new InputStreamReader(System.in)));
		int n, m;
		while (in.nextToken() != StreamTokenizer.TT_EOF)
		{
			n = (int) in.nval;
			in.nextToken();
			m = (int) in.nval;
			init(n);
			for (int i = 1; i <= m; i++)
			{
				in.nextToken();
				int p1 = (int) in.nval;
				in.nextToken();
				int p2 = (int) in.nval;
				if (v[p1][p2] == 0)
				{
					inDegree[p2]++;
				}
				v[p1][p2] = 1;
			}
			topologicalOrder(n);
			System.out.println();
		}
	}

	private static void topologicalOrder(int n)
	{
		// TODO Auto-generated method stub
		int vv;
		Queue<Integer> queue = new PriorityQueue<Integer>();
		for (int i = 1; i <= n; i++)
		{
			if (inDegree[i] == 0)
			{
				queue.add(i);
			}
		}
		for (int i = 1; i <= n; i++)
		{
			vv = queue.poll();
			for (int j2 = 1; j2 <= n; j2++)
			{
				if (v[vv][j2] > 0)
				{
					inDegree[j2]--;
					if (inDegree[j2] == 0)
					{
						queue.add(j2);
					}
				}
			}
			System.out.print(vv);
			if (i != n)
			{
				System.out.print(" ");
			}
		}

	}

	private static void init(int n)
	{
		// TODO Auto-generated method stub
		for (int i = 1; i <= n; i++)
		{
			for (int j = 1; j <= n; j++)
			{
				v[i][j] = 0;
			}
			inDegree[i] = 0;
		}

	}

}
直接把入度为0的顶点放到优先队列中(普通的拓扑排序只用普通队列/栈/数组即可,这里题目中有要求,相同入度为0的点要求序号小的先输出,所以使用优先队列),使用队列减少了一遍遍的遍历所有点的入度。


在使用BFS和Dijkstra的优先队列中都要使用到队列,关于Dijkstra以及最短路径算法,请查看最短路径算法



系列:

【算法系列 一】 Linked List

【算法系列 二】 Stack

【算法系列 三】 Quene

【算法系列 四】 String

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!