贪婪算法——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;
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值