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