好玩的Prim算法
这段时间学算法,用JS实现了一个Prim,用于在连通图中找出最小树,具体内容、代码解析周末会不上,现在先把源码献上:
<!DOCTYPE html>
<html charset='GB2312'> <head>
<title>最小树生成算法</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <style type="text/css">
body>canvas {
border: 1px solid black;
padding: 10px;
margin: 10px auto;
}
</style>
</head> <body>
<canvas id="canvas" width="1000px" height="400px"></canvas>
<canvas id="sub-canvas" width="1000px" height="400px"></canvas>
<script type="text/javascript">
!(function() {
var canvas_context = document.getElementById('canvas').getContext('2d'),
sub_ctx = document.getElementById('sub-canvas').getContext('2d'),
_getRandom = function(max, min) {
max = max || 100;
min = min || 0;
return Math.round(Math.random() * (max - min) + min);
},
_getRandomMatix = function(nodes) {
var matix = [],
power = 0,
max = 10,
min = 0,
tmp = 0;
for (var i = 0; i < nodes; i++) {
for (var j = i; j < nodes; j++) {
power = _getRandom(max, min);
matix[i] = matix[i] || [];
matix[j] = matix[j] || [];
tmp = i === j ? 0 : (Math.random() > 0.6 ? 1 : 0) * power;
matix[i][j] = matix[j][i] = tmp;
}
console.log(matix[i].join(','))
} // 构造连通图
for (var i = 0; i < matix.length; i++) {
var isValid = true;
for (var j = 0; j < matix[i].length; j++) {
isValid = isValid && matix[i][j] !== 0;
}
if (!isValid) {
var rindex = _getRandom(matix[i].length - 1, 0),
v = _getRandom(max, min + 1);
matix[i][rindex] = matix[rindex][i] = v;
}
}
return matix;
},
_matix2graph = function(matix) {
var len = matix.length,
row = null,
cell = null,
graph = {},
x,
y;
canvas_context.font = cycle_width / 2 + 'px Arial bold';
canvas_context.textAlign = 'center';
for (var i = 0; i < len; i++) {
x = _getRandom(pain_rect.x2, pain_rect.x1);
y = _getRandom(pain_rect.y2, pain_rect.y1); graph[i] = {
x: x,
y: y,
powers: matix[i]
}
}
return graph;
},
_getMinTree = function(graph) {
var point1 = graph[0],
min_tree = {
x: point1.x,
y: point1.y,
index: 0,
sub: []
},
min_x = -1,
min_y = -1,
min = Number.MAX_VALUE,
index_inTree = [0],
node = null,
_findNode = function(index, roots) {
if (roots.length === 0) return null; var subRoots = [];
for (var i in roots) {
if (roots[i].index === index) return roots[i];
else subRoots = subRoots.concat(roots[i].sub);
}
return _findNode(index, subRoots);
}; for (var k in graph) {
min_x = -1;
min_y = -1;
min = Number.MAX_VALUE;
for (var i = 0; i < index_inTree.length; i++) {
point1 = graph[index_inTree[i]];
for (var j = 1; j < point1.powers.length; j++) {
if (index_inTree.indexOf(j) >= 0) continue;
else if (point1.powers[j] > 0 && point1.powers[j] < min) {
min_x = point1.index;
min_y = j;
min = point1.powers[j]
}
}
}
if (min_x >= 0) {
index_inTree.push(min_y);
point1 = graph[min_y];
node = _findNode(graph[min_x].index, [min_tree]);
if ( !! node) node.sub.push({
x: point1.x,
y: point1.y,
index: min_y,
power: min,
sub: []
});
}
console.log('min tree node count: ' + index_inTree.length + ' ; ' + node);
}
return min_tree;
},
canva_width = 1000,
canva_height = 400,
x_range = 490,
y_range = 190,
pain_rect = {
x1: canva_width / 2 - x_range,
x2: canva_width / 2 + x_range,
y1: canva_height / 2 - y_range,
y2: canva_height / 2 + y_range
},
cycle_width = 10,
_renderGraph = function(graph) {
var point1,
point2,
count = 0;
for (var i in graph) {
point1 = graph[i];
i = i - 0;
point1.index = i;
for (var j = 0; j < point1.powers.length; j++) {
point2 = graph[j];
point2.index = j; _renderPoint(point1);
_renderPoint(point2);
if ( !! point1.powers[j]) {
_renderLine(point1, point2, point1.powers[j]);
console.log('graph ' + i + ' to ' + j + ': ' + point1.powers[j]);
count += point1.powers[j];
}
}
}
console.log('end graph :' + count);
return graph;
},
_renderTree = function(tree) {
var _count = 0,
_renderer = function(root) {
var point1 = root,
point2 = null;
_renderPoint(point1, sub_ctx);
for (var i = 0; i < root.sub.length; i++) {
point2 = root.sub[i];
_renderLine(point1, point2, point2.power, sub_ctx);
_renderer(point2);
_count += point2.power;
console.log('tree ' + point1.index + ' to ' + point2.index + ' : ' + point2.power);
}
};
_renderer(tree); console.log('end tree :' + _count)
},
_renderPoint = function(point1, ctx) {
ctx = ctx || canvas_context;
requestAnimationFrame(function() {
// 画点
ctx.beginPath();
ctx.fillStyle = 'red';
ctx.arc(point1.x, point1.y, cycle_width, 0, Math.PI * 2, true);
ctx.fill();
ctx.closePath(); // 点中间的字——点的序号
ctx.beginPath();
ctx.fillStyle = 'white';
ctx.fillText(point1.index, point1.x, point1.y + cycle_width / 4);
ctx.closePath();
});
},
_renderLine = function(point1, point2, power, ctx) {
ctx = ctx || canvas_context; requestAnimationFrame(function() {
// 点与点间的连线
ctx.beginPath();
ctx.moveTo(point1.x, point1.y);
ctx.lineTo(point2.x, point2.y);
ctx.closePath();
ctx.stroke(); // 点与点间连线的字——权重
ctx.beginPath();
ctx.fillStyle = 'red';
var x1 = Math.min(point1.x, point2.x),
x2 = Math.max(point1.x, point2.x),
y1 = Math.min(point1.y, point2.y),
y2 = Math.max(point1.y, point2.y);
ctx.fillText(power, 0.5 * x2 + 0.5 * x1, 0.5 * y2 + 0.5 * y1);
ctx.closePath();
});
}; var graph = _renderGraph(_matix2graph(_getRandomMatix(9)));
_renderTree(_getMinTree(graph))
})();
</script>
</body> </html>
这里可以在线运行哦:http://www.w3cfuns.com/home.php?mod=space&uid=5446932&do=blog&quickforward=1&id=5398698
好玩的Prim算法的更多相关文章
- 经典算法题每日演练——第十四题 Prim算法
原文:经典算法题每日演练--第十四题 Prim算法 图论在数据结构中是非常有趣而复杂的,作为web码农的我,在实际开发中一直没有找到它的使用场景,不像树那样的频繁使用,不过还是准备 仔细的把图论全部过 ...
- 图的生成树(森林)(克鲁斯卡尔Kruskal算法和普里姆Prim算法)、以及并查集的使用
图的连通性问题:无向图的连通分量和生成树,所有顶点均由边连接在一起,但不存在回路的图. 设图 G=(V, E) 是个连通图,当从图任一顶点出发遍历图G 时,将边集 E(G) 分成两个集合 T(G) 和 ...
- 最小生成树のprim算法
Problem A Time Limit : 1000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other) Total Sub ...
- 数据结构代码整理(线性表,栈,队列,串,二叉树,图的建立和遍历stl,最小生成树prim算法)。。持续更新中。。。
//归并排序递归方法实现 #include <iostream> #include <cstdio> using namespace std; #define maxn 100 ...
- 最小生成树——prim算法
prim算法是选取任意一个顶点作为树的一个节点,然后贪心的选取离这棵树最近的点,直到连上所有的点并且不够成环,它的时间复杂度为o(v^2) #include<iostream>#inclu ...
- 洛谷 P3366 【模板】最小生成树 prim算法思路 我自己的实现
网上有很多prim算法 用邻接矩阵 加什么lowcost数组 我觉得不靠谱 毕竟邻接矩阵本身就不是存图的好方法 所以自己写了一个邻接表(边信息表)版本的 注意我还是用了优先队列 每次新加入一个点 ...
- 最小生成树算法——prim算法
prim算法:从某一点开始,去遍历相邻的边,然后将权值最短的边加入集合,同时将新加入边集中的新点遍历相邻的边更新边值集合(边值集合用来找出新的最小权值边),注意每次更新都需将cost数组中的点对应的权 ...
- 贪心算法-最小生成树Kruskal算法和Prim算法
Kruskal算法: 不断地选择未被选中的边中权重最轻且不会形成环的一条. 简单的理解: 不停地循环,每一次都寻找两个顶点,这两个顶点不在同一个真子集里,且边上的权值最小. 把找到的这两个顶点联合起来 ...
- Prim算法(三)之 Java详解
前面分别通过C和C++实现了普里姆,本文介绍普里姆的Java实现. 目录 1. 普里姆算法介绍 2. 普里姆算法图解 3. 普里姆算法的代码说明 4. 普里姆算法的源码 转载请注明出处:http:// ...
随机推荐
- 窗体DataGridView控件中按回车键时,单元格向下移动,如何能改成向右移动
方法一:protected override void OnKeyUp(System.Windows.Forms.KeyEventArgs e) { base.OnKeyUp(e); if (e.Ke ...
- MAVEN整理(乘国庆还有时间,停下来整理一下)
昨天写下了这篇博客(http://www.cnblogs.com/hzmark/p/131003Release.html),今天有时间,就这里一下第一篇内容. 换工作公司开发平台: WINDOWS+V ...
- R语言画图布局摆放(layout)
require(ggplot2) require(Cairo) require(grid) p = ggplot(iris,aes(x = Species,y = Sepal.Length,colou ...
- EXCEL IF 函数 模糊查询
A列都是产品名,比如衬衫,长袖衬衫,短袖衬衫,短裙,长裙 搜索A列的产品名,凡是含有“衬衫”的一律在B列对应行输出“衬衫”,凡是含有“裙”字的一律输出“裙子”在B列对应行,请教一下怎么写函数,本来用I ...
- Redhat6.5 安装64位oracle11.2.0.1
系统架构 [root@localhost ~]# uname -a Linux db 2.6.32-431.el6.x86_64 #1 SMP Sun Nov 10 22:19:54 EST 2013 ...
- OpenXml入门----给Word文档添加文字
使用OpenXml给word文档添加文字,每个模块都有自己对于的属性以及内容,要设置样式就先声明属性对象,将样式Append到属性里面,再将属性append到模块里面,那么模块里面的内容就具备该样式了 ...
- HOJ 1640 Mobile Phone
题意:有一个n*n的矩阵,op==1时,在(x,y)增加值z,op==2时,求以(x1,y1)和(x2,y2)构成的矩阵的和. 思路:二维线段树. 代码: #include<stdio.h> ...
- C#泛型简化代码量示例
泛型简化代码量 下是我在项目中通过泛型来简化工作的一个Demo,记录一下: using System; using System.Collections.Generic; namespace My ...
- java14-9 Doteformat的练习
需求: 键盘录入出生年月日,计算出距离现在已经生活了几天 分析: A:创建键盘录入固定模式的字符串 B:计算步骤: a:把输入进来的字符串格式化成日期 b:获取现在的日期,减去格式化后的日期 c:把得 ...
- android studio 导入工程问题总结
github上下了几个开源项目,在导入android studio时出现各种问题, 在网上查询各种资料后一一得以解决,现对个问题点进行简单的总结: 1. gradle project sync fai ...