好玩的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:// ...
随机推荐
- NetBIOS
NetBIOS是Network Basic Input/Output System的缩写,严格来说它不是一个网络协议,而是一套API,为局域网内应用程序通信提供会话层(OSI七层参考模型)的支持. N ...
- linux搭建mysql 5.6.28
1.下载rmp文件 http://dev.mysql.com/downloads/mysql/ 2.安装 rpm -ivh MySQL-server--.linux_glibc2..x86_64.rp ...
- O(N)时间的排序
题目:某公司有几万名员工,请完成一个时间复杂度为O(n)的算法对该公司员工的年龄作排序,可使用O(1)的辅助空间. 要注意分析题目,一般排序要么是O(n^2),要么是O(nlogn).但这里题目特别强 ...
- Android 系统架构
Android 系统从下至上分为四层:Linux 内核.Android 核心库及Android 运行时环境(Android Runtime). 应用程序框架以及应用程序等. Linux 内核(Linu ...
- [转]后台页面访问权限:页面基类&内置票据认证 使用方法
本文转自:http://www.cnblogs.com/fishtreeyu/archive/2011/01/29/1947421.html 一般网站后台页面除了登录页面login.aspx未登录用户 ...
- 【MVC 4】7.SportsSore:完成购物车
作者:[美]Adam Freeman 来源:<精通ASP.NET MVC 4> 本文将继续构建 SportsStore 示例应用程序.在上一章中,添加了对购物车的基本支持,现在打 ...
- SGU 180 Inversions
题意:求逆序数对数量. 思路一:暴力,O(N^2),超时. 思路二:虽然Ai很大,但是n比较小,可以离散化,得到每个Ai排序后的位置Wi,然后按照输入的顺序,每个Ai对答案的贡献是Wi-Sum(Wi- ...
- 分布式监控系统Zabbix-3.0.3-完整安装记录(5)-邮件报警部署
前面几篇陆续介绍了zabbix3.0.3监控系统的部署和监控项配置,今天这里分享下zabbix3.0.3的邮件报警的配置过程~由于采用sendmail发送邮件,常常会被认为是垃圾邮件被拒,所以不推荐这 ...
- localStroage的用法
Cookie 每个域名存储量比较小(各浏览器不同,大致4K) 所有域名的存储量有限制(各浏览器不同,大致4K) 有个数限制(各浏览器不同) 会随请求发送到服务器 LocalStorage 永久存储 单 ...
- PHP openssl加密扩展使用总结
1.检查服务器是否已安装了openssl组件,没有则先安装好 openssl version [-a] 2.对称加密 查询openssl支持的对称加密算法 openssl_get_cipher_met ...