图形算法可视化

最近看了一些和图形、算法可视化相关的文章和代码,挺有意思,于是自己也学着做了些东西。

迷宫生成算法

迷宫小时候玩过,但从来没琢磨过迷宫是怎么设计的,以为就是有人慢慢画出来的。看过网上这篇文章后,才知道,原来还可以随机生成:

Maze Generation - Visualizing Algorithms

自己找了些资料参考,试着实现了几种之后,才慢慢领会到其中的一些原理。

算法中讨论的迷宫满足一个条件:迷宫中任意两点间有且只有一条路径

要随机生成满足这样条件的迷宫,看起来很复杂啊。但是换个思路之后,就发现问题没那么复杂了。

“树”其实就满足这个条件:

  • 所有的枝叶都可以通过树枝、树干连通
  • 由于枝干不交叉,没有环,所以枝叶间连通的路径是唯一的

所以,生成随机的迷宫的问题,就转化为生成随机的树的过程。进一步,可以拆分为以下过程:

  • 在迷宫网格内随机选择一个点作为“树根”
  • 从树根开始,向随机选择的某一方向开始生长
  • 直到树的枝干通过不断生长、分叉充满迷宫的所有网格

迷宫生成的不同算法,区别主要在两点:

  • 从一个位置开始生成后一直向随机方向延伸的最大长度:有的是延伸一个网格后立即更换生长点,有的则是直到无法继续延伸后才更换生长点
  • 更换生长点时选择位置的方式:有的是记录当前枝干经过的网格,依次后退,有的干脆是完全随机选择一个有可能向外生长的点

深度优先算法

深度优先算法,也叫递归回溯算法。它会一直向随机方向生长,直到无法生成的位置,向后回退一格,继续生长,直到所有网格被填充。

深度优先算法生成的迷宫

深度优先算法生成的迷宫,会有比较明显的长路径,这是因为树在一开始生成的时候,空间比较充裕,会有一些长的枝条产生。

Prim 算法

Prim 算法不会一直沿着一条路径进行探索,而是不断尝试随机的生长点。所以 Prim 算法生成的迷宫,分叉会比较多:

Prim 算法生成的迷宫

算法实现

综合以上两种算法,我既不希望有过长的路径,也不希望有太多的分叉,所以我采用的思路的尝试沿着一条路径延伸最多一定的长度,然后再随机选择生长点执行相同的过程。

下图是在 40*40 的迷宫网格,每条枝干最多生长15个网格的效果:

迷宫生成算法 - 开始

这是执行了一段时间之后,迷宫大部分区域已经走过:

迷宫生成算法 - 执行中

这是最后的效果:

迷宫生成算法 - 完成

项目地址:luobotang/maze
在线DEMO:迷宫生成算法 - luobotang

算法可视化

上面例子中的迷宫生成算法过程,迷宫网格是通过 HTML 的 <table> 实现,相邻网格的连通效果,则是借助 CSS 的边框样式。

整个迷宫的所有网格由二维数组表示,每个网格的状态包含是否被访问、与相邻网格的连通情况等。

算法的执行过程由定时器驱动,每次执行一步,从而有动画的效果。

最短路径算法

与图相关的最短路径算法,在生活中应该是有着广泛的应用了吧,从一个位置到另一个位置,借助已有的路网,计算最短的路径。当然,还会因为路况、临时障碍,以及用户的个人偏好而产生不同结果。

对于“图”上,基本要素就是:

  • 节点
  • 边:根据场景的不同,还会有方向、权重属性

Dijkstra 算法

Dijkstra 算法是用于计算最短路径的比较著名的一种算法,早在1956年就发表了。

Dijkstra 算法如果看算法的详细执行过程,有点复杂,但是其基本思路在做过之后会发现,貌似很简单。

已确定 A 到 B 的最短路径,B 与 C 相连,且 A 到 B 的距离加上 B 到 C 的距离,小于当前 A 到 C 的距离,那么 A 到 B 再到 C 就是 A 到 C 的最短路径。

图示例

如上图所示,最初从 A 来看,到 C 的最短路径是 A -> C,距离是 4。但继续探索到 B 后,发现 A -> B 加上 B -> C 距离只有 3,比 A -> C 的距离要小,所以 A 到 C 的最短路径更新为:A -> B -> C。

算法实现

基本思路上面都介绍了,细节就是每次探索节点时,都选择当前未探索过的到源点距离最短的节点,这样可以源点到当前点的路径已经是最短路径。

算法可视化

图的可视化比较复杂了,只是绘制出来其实不难,但要将节点、边进行合理布局就比较麻烦,是另一个话题了。

我选择用 vis.js 提供的 Network 来绘制图形,然后通过逐步执行算法来更新图形。

这是初始状态:

Dijkstra 算法 - 开始

执行过程中,会记录节点是否被访问,以及当前的最短路径和对应的距离:

Dijkstra 算法 - 执行中

全部执行完成后,就得到了源点开始到图中所有节点的最短路径:

Dijkstra 算法 - 完成

项目地址:luobotang/graph
在线DEMO:Dijkstra 算法 - luobotang

结语

其实上面这些实现起来并没有特别困难,有很多现成的资料和代码可以利用。但是不管什么饭,都得自己吃过、消化过才是自己的。所以,我把自己吸收的“营养”记录下来,如果你也有兴趣,不妨自己上手一试。

最后,感谢阅读!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容