数据结构-基于邻接矩阵实现图的遍历可视化及使用Floyd、Dijkstra算法求解最短路径(JavaScript实现)

使用 JavaScript 基于邻接矩阵实现了图的深度、广度遍历,以及 Floyd、Dijkstra 算法求解最短路径。

另外使用 SVG 实现图的遍历可视化。

一、输入

首先,输入数据主要有两个,一个是存放节点名的数组,另一个是存放边对象的数组。

例如:

//存放图结点的数组
var graphVertex = ["v0","v1","v2","v3","v4","v5","v6"];
//存放图边的数组
var graphAdge = [
	{
		start:"v0",
		end: "v2",
		weight: 2
	},
	{
		start:"v0",
		end: "v5",
		weight: 8
	},
	{
		start:"v3",
		end: "v2",
		weight: 1
	},
	{
		start:"v3",
		end: "v5",
		weight: 3
	},
	{
		start:"v4",
		end: "v1",
		weight: 6
	},
	{
		start:"v5",
		end: "v4",
		weight: 8
	},
	{
		start:"v1",
		end: "v2",
		weight: 8
	},
	{
		start:"v1",
		end: "v6",
		weight: 8
	}
];


二、SVG画图

使用SVG画出圆形结点、节点名、边、边的权值数字以及表示有向图的箭头。

//显示图
var showGraph = function(){
	var svg = document.getElementById("svg");
	var circleStr = "",lineStr = "",textStr = "",arrowStr="";//圆、线和文本的HTML字符串
	var adge = JSON.parse(JSON.stringify(graphAdge));//层序遍历生成数组
	var vertex = JSON.parse(JSON.stringify(graphVertex));//层序遍历生成数组
	var vertexObj = {};//存放所有顶点的对象,键为顶点名,值为含有属性的对象
	var width = Number(svg.getAttribute("width"))-50;//画布宽度
	var r = width/2;//半径
	//画圆和顶点名
	for(let i=0;i<vertex.length;i++){
		let vertexName = vertex[i], len = vertexName.length;
		let angle = (i*2*Math.PI/vertex.length);
		let cx = 0, cy = 0;//当前结点的定位像素坐标
		cx = r*(1 + Math.sin(angle) )+25;
		cy = r*(1 - Math.cos(angle) )+25;
		let obj = {
			"cx":cx,
			"cy":cy
		};
		vertexObj[vertexName] = obj;
		circleStr += '<circle cx="'+cx+'" cy="'+cy+'" r="20" fill="#9F79EE"/></circle>';
		//调整文本缩进
		let textcx = len>1?(cx-10):(cx-5);
		let textcy = cy+6;
		textStr += '<text x="'+textcx+'" y="'+textcy+'" fill="black">'+vertexName+'</text>';
	}
	//画线和数字
	for(let i =0;i<adge.length;i++){
		//如果依然处于当前层,则累加占用宽度,否则将占用宽度置零,更新层数
		
		let startcx = 0, startcy = 0,endcx = 0,endcy = 0;//当前结点的定位像素坐标

		if(!vertexObj[adge[i].start]||!vertexObj[adge[i].end]){
			throw Error("边数组中有结点不在结点数组中");
			return;
		}
		startcx = vertexObj[adge[i].start].cx;
		startcy = vertexObj[adge[i].start].cy;
		endcx = vertexObj[adge[i].end].cx;
		endcy = vertexObj[adge[i].end].cy;
		lineStr += '<line x1="'+startcx+'" y1="'+startcy+'" x2="'+endcx+
			'" y2="'+endcy+'" style="stroke:#999;stroke-width:2" />';

		//计算三角形箭头的坐标和旋转角
		var getTriangle = function(obj){
			var x = endcx,y=endcy+20;
			startcx = obj.startcx;
			startcy= obj.startcy;
			endcx= obj.endcx;
			endcy= obj.endcy;
			var x = endcx, y = endcy+20;
			var points = [x-7,y+15,x+7,y+15,x,y].join(",");//一个三角形三点的坐标
			var angle = 0;
			//注意这里的坐标系和通常情况下的坐标系y轴是相反的,因此 endcy-startcy 要变为startcy-endcy
			angle =180*Math.acos((startcy-endcy)/Math.sqrt((endcx-startcx)*(endcx-startcx)+
				(startcy-endcy)*(startcy-endcy)))/Math.PI;
			if(endcx-startcx < 0){
				angle = 360 - angle;
			}
			var out = {
				"points":points,
				"angle":angle
			}
			return out;
		}
		//如果是无向图隐藏下面计算与画三角形箭头的代码即可
		var obj = {
			"startcx":startcx,
			"startcy":startcy,
			"endcx":endcx,
			"endcy":endcy
		}
		var data = getTriangle(obj);
		var angle = [data.angle,endcx,endcy].join(",");
		//画三角形箭头
		arrowStr += '<polygon points="'+data.points+'" fill:"#171717" transform="rotate('+angle+')"/>';
		
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值