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

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值