貪婪算法——3 Dijkstra算法

/**
 * Dijkstra算法(單起點最短路徑) <br/>
 * 基於貪婪算法,每次各點到起點的距離中選出最小權重(該值u初始值爲點到起點的距離, 如果點沒有連接起點的邊,則值爲正無窮)的點n加入到樹中
 * ,新加入點應該有一個值記錄到起點的距離d,在遍歷剩下未加入樹的點,如果當前點u值大於新加入點n到當前點的距離d1+d,
 * 則當前點將更新爲d1+d,如此重複,直至全部點加入樹
 * 
 * <br/>
 * 每個節點必須有兩個標記:(1)起點到頂點的最短路徑 (2)頂點父母 <br/>
 * <br/>
 * 加入樹中的節點u*後: <br/>
 * (1)把u*從邊緣集合中移動到樹頂點集合 <br/>
 * (2)對餘下的每一個邊緣節點u,如果通過權重w(u*,u)的邊和u*相連,當du* + w(u*,u) < du時,把u的標記分別更新爲du* +
 * w(u*,u)
 * 
 * @author chenxuegui
 * 
 */
public class Dijkstra
{

	// 存儲未加入樹的節點同樹中點的最小距離
	private static Map<String, Distance> map;

	// 存儲加入的邊
	private static List<Distance> tree;

	private static String origin = null;

	public static void main(String[] args)
	{
		int[][] a = new int[5][5];

		tree = new ArrayList<>();
		map = new HashMap<>();
		String cur = null;

		init(args, a, 5);
		cur = origin;
		int preDis = 0;

		map.remove(origin);

		while (map.size() != 0)
		{

			traverse(cur, a, 5, preDis);
			Distance minDis = find();
			tree.add(minDis);

			cur = minDis.getVertex();
			preDis = minDis.getWeight();
		}

		System.out.println(tree);

	}

	/**
	 * 初始化
	 */
	private static void init(String args[], int[][] a, int n)
	{
		int i = 0;

		for (; i < n * n; i++)
		{
			a[i / n][i % n] = Integer.valueOf(args[i]);
		}

		origin = args[i++];

		n += i;

		for (; i < n; i++)
		{
			map.put(args[i], new Distance(args[i], null, Integer.MAX_VALUE));
			System.out.println(args[i]);
		}
	}

	/**
	 * 從Map<String, Distance>中查找權值最小的關係對應的邊 返回邊
	 * 
	 * @return
	 */
	public static Distance find()
	{
		String key = null;
		int minWeight = Integer.MAX_VALUE;

		for (Entry<String, Distance> entry : map.entrySet())
		{
			if (minWeight > entry.getValue().getWeight())
			{
				key = entry.getKey();
				minWeight = entry.getValue().getWeight();
			}
		}

		// 約束:把map.key(未加入樹的點)放在vertex1
		Distance d = map.get(key);
		map.remove(key);

		return d;
	}

	/**
	 * 從cur vertex中對各既在map中又在權值比map中小的點跟新到map中
	 * 
	 * @param vertex
	 *            上一個加入map的節點
	 * @param a
	 * @param n
	 * @param preDis
	 *            上一個節點到起點的距離
	 */
	public static void traverse(String vertex, int[][] a, int n, int preDis)
	{
		Distance distance;
		String s;

		int index = vertex.charAt(0) - 97;

		for (int i = 0; i < n; i++)
		{
			s = "" + (char) (i + 97);

			if (i != index && map.get(s) != null)
			{
				distance = map.get(s);

				if (distance.getWeight() > a[index][i] + preDis
						&& a[index][i] != 0)
				{
					distance.setWeight(a[index][i] + preDis);
					distance.setParentVertex(vertex);
				}

			}

		}

	}
}

/**
 * 
 * @author Administrator
 * 
 */
class Distance
{
	/**
	 * 該節點
	 */
	private String vertex;

	/**
	 * 該節點的父節點,即與當前節點連着的邊的另一個節點
	 */
	private String parentVertex;

	/**
	 * 兩個點所在邊的權值
	 */
	private int weight;

	public Distance(String vertex, String parentVertex, int weight)
	{
		this.vertex = vertex;
		this.parentVertex = parentVertex;
		this.weight = weight;
	}

	public String toString()
	{
		return "(" + this.parentVertex + " : " + this.vertex + "value: "
				+ this.getWeight() + ")";
	}

	public String getVertex()
	{
		return vertex;
	}

	public void setVertex(String vertex)
	{
		this.vertex = vertex;
	}

	public String getParentVertex()
	{
		return parentVertex;
	}

	public void setParentVertex(String parentVertex)
	{
		this.parentVertex = parentVertex;
	}

	public int getWeight()
	{
		return weight;
	}

	public void setWeight(int weight)
	{
		this.weight = weight;
	}

}

点赞