【算法系列 三】 Quene

1. 拓撲排序問題(HDU 1285) php

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以及最短路徑算法,請查看最短路徑算法
java



系列: 算法

【算法系列 一】 Linked List 數組

【算法系列 二】 Stack 優化

【算法系列 三】 Quene spa

【算法系列 四】 String .net

相關文章
相關標籤/搜索