貪婪算法——1 Prim算法

/**
 * Prim 算法構建最小生成樹(節點必須含有權重)<br/>
 * 
 * 當中每個頂點包含兩個標記:(1)指出了最近的樹中頂點和邊的權重; (2)被選中的頂點和邊加粗表示<br/>
 * 
 * 加入節點u:<br/>
 * (1)把u*從集合V-Vt移動到樹的頂點集合Vt中(V爲已加入樹的節點的集合,Vt爲還沒加入樹的節點的集合)<br/>
 * (2)對於集合V-Vt中每一個剩下的頂點u,如果它用一條比u當前距離標記更短的變和u*相連,分別把它的標記更新爲u*以及u與u*之間的權重<br/>
 * <br/>
 * test: 0 3 0 6 5 3 0 1 0 4 0 1 0 0 4 6 0 0 0 2 5 4 4 2 0<br/>
 * test: 0 3 0 0 6 5 3 0 1 0 0 4 0 1 0 6 0 4 0 0 6 0 8 5 6 0 0 8 0 2 5 4 4 5 2 0
 * 
 * <br/>算法效率:<br/>鄰接矩陣,優先隊列數組 O(V^2)
 * <br/>鄰接鏈表,優先隊列堆 O(ElogV)
 * @author chenxuegui
 * 
 */
public class Prim
{
	// 節點數
	static int i = 6;

	// 輸入5個點的權重舉證
	public static void main(String[] args)
	{

		int[][] weight = new int[i][i];

		// 初始化權重矩陣,沒有通路的以0表示
		for (int k = 0; k < i * i; k++)
		{
			weight[k / i][k % i] = Integer.valueOf(args[k]);
		}

		// 用hash隊列充當優先隊列
		Map<Integer, Integer> map = new HashMap<>();

		// 節點輸出的順序
		List<Integer> list = new ArrayList<>();

		// 初始化優先隊列
		for (int k = 0; k < i; k++)
		{
			map.put(k, k == 0 ? -1 : weight[0][k]);
		}

		Prim p = new Prim();

		p.prim(weight, map, list, i);

		for (int i : list)
		{
			System.out.println(i);
		}

	}

	/**
	 * 
	 * 實現prim算法的核心部分,加入權值最小的點
	 * 
	 * @param weight
	 * @param map
	 * @param list
	 * @param i
	 *            節點數
	 * @param u
	 *            上一個加入節點
	 */
	private void prim(int[][] weight, Map<Integer, Integer> map,
			List<Integer> list, int i)
	{

		for (int k = 0; k < i; k++)
		{
			Iterator<Integer> it = map.keySet().iterator();

			// 取得當前優先隊列中最優選擇
			int minKey = 0;
			int minValue = Integer.MAX_VALUE;
			while (it.hasNext())
			{
				int key = it.next();

				if (map.get(key) < minValue && map.get(key) != 0)
				{
					minValue = map.get(key);
					minKey = key;
				}
			}

			// 把當前最優點(即距離最短的點)加入list中
			list.add(minKey);
			map.remove(minKey);

			// 跟新當前優先隊列中的點的權值
			it = map.keySet().iterator();
			while (it.hasNext())
			{
				int key = it.next();

				int value = map.get(key);

				if ((map.get(key) > weight[minKey][key] && weight[minKey][key] != 0)
						|| (map.get(key) == 0))
					value = weight[minKey][key];

				map.put(key, value);
			}
		}
	}

}
点赞