好玩的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:// ...
随机推荐
- Eclipse++Xdebug开发php环境配置
一.php环境配置: 本次使用了appserv 2.5.10集成安装包.具体版本如下,安装后php版本是5.2.6 vc6,apache版本2.2 安装完成后,php配置文件在c:\windows目录 ...
- sql 把特定数据排在最前面
感谢www.baidu.com/p/dongfanghong_1 sql大神,简单的语法运用起来简直活了. 第一法] select * from table where name='D' UNION ...
- 虚拟机centos6.5 --设置主机名
vi /etc/sysconfig/network #修改HOSTNAME后面的值,机器名 vi /etc/hosts #设置ip和机器名的对应关系 192.168.12.232 master 192 ...
- OpenXml入门----给Word文档添加文字
使用OpenXml给word文档添加文字,每个模块都有自己对于的属性以及内容,要设置样式就先声明属性对象,将样式Append到属性里面,再将属性append到模块里面,那么模块里面的内容就具备该样式了 ...
- openfire+asmack搭建的安卓即时通讯(二) 15.4.9
上期没有放成果图呢!忘了=-=,这就是上次的成果图,textview里面会显示登陆的名字(这个是默认管理员帐号=-=) 好吧,登陆了服务器我们就有了交互的功能啦可以说是前进了一大步呢!下面能我们就要试 ...
- 软件工程实训项目案例--Android移动应用开发
实训过程 角色分工 1.项目经理:负责项目的组织实施,制定项目计划,并进行跟踪管理 2.开发人员:对项目经理及项目负责 3.需求分析员:负责系统的需求获取和分析,并协助设计人员进行系统设计 4.系统设 ...
- 第8课 goto 和 void 分析
1. 遭人遗弃的goto (1)高手潜规则:禁用goto (2)项目经验:程序质量与goto出现的次数成反比 (3)最后的判决:将goto打入冷宫(1)循环语句的基本工作方式 [实例分析]goto副作 ...
- java 15 -3 集合的遍历的练习
练习:用集合存储5个动物对象,并把动物对象进行遍历. 分析: A:创建动物类 a:无参构造方法 b:有参构造方法 c:get.set方法 B:创建集合对象 a:Collection animal = ...
- java 12-4 StringBuffer类的替换、反转、截取功能
1.StringBuffer的替换功能: public StringBuffer replace(int start,int end,String str):从start开始到end用str替换 pu ...
- Jsp页显示时间标签JSTL标签 <fmt:formatDate/> 实例大全
<fmt:formatDate value="${isoDate}" type="both"/>2004-5-31 23:59:59 <fmt ...