大二开始学习数据结构,老师的讲课方式就是PPT照本宣科,讲解算法就是把代码的部分贴出来一行一行细讲......基本每节课除了只知道老师讲了什么内容,内容的思想我可以说是0%吸收,于是我便打算自学。
自学的路上我走了不少坑,比如通过看自学书的代码来弄懂算法思想,结果发现是本末倒置。学到现在,我感觉数据结构大体分为两个部分:概念阐述和算法实现,相比概念,算法实现的学习最后必须依靠线上,所花的时间成本也远大于概念学习,我觉得像老师那样把代码放在幻灯片上细讲的做法纯粹在浪费时间。因为放映的都是某部分功能而不是整套算法,学的时候很难把眼前算法里的一些变量跟最上面的typedef的各种属性联系起来,再联系到结构图例以弄清楚是讲了什么,课上先讲的ADT在脑子里记不住,老师就就跳转到算法上去了,最后导致尽管看懂了概念,看代码却依然如天书一般,看不到最后的输出(既背后的数据结构整个操作的过程)。
基于“所想的事物肯定都有人实践过了”的想法,我便搜索了一番。目前找到了四个网页:
前三个已经被各路大佬介绍了无数遍了,但基本都是对网站的简单介绍,我想把自己的实践也记录下来:
(一)Visualgo https://visualgo.net/en
这估计是最为知名可视化网站了,也是我第一个找到的网站,可以自己绘制图结构,但是右边的代码执行过程,我这个只会C和Javascript的菜鸟看的一脸懵逼。
此外这个网站有部分算法并未收录,比如Floyd的最短路径算法(Floyd-Warshall's Shortest Path)和拓补排序(topological sort)算法就没有。
(二)Algorithm Visualizer https://algorithm-visualizer.org/
一个Github项目,算法演示代码为Javascript,可以修改代码来改图结构(话说这存储图结构用的都是领接矩阵),但似乎有bug,记得我有一次改prim算法的图运行时动画就不动了,只好改回默认图。
图的点可以拖动,但是运行的时候一把步骤往回拖图又会变成默认的样子,很烦。
另外可视化的效果也不怎么样,比如这个Dijkstra的算法和Visualgo的一对比。。。一个什么都没有,一个还能把点的占有关系显示出来
(三) Data Structure Visualizations https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
旧金山大学开发的,从名字就知道主要是讲数据结构,对现在还在学数据结构的我是最适合不过了,不过算法操作过程是用矢量图演示的,图结构随机生成,没法自己设定,也没有实例代码,但是看算法的操作过程够用了。
(话说它这Dijkstra的算法是从开始点到所有点的,而我学习的是单点对单点)
(四)pythontutor http://pythontutor.com/
《算法图解》作者实例代码库(https://github.com/egonschiele/grokking_algorithms)的附加推荐!,支持把C,Java,Python,Ruby等代码的调试过程可视化,对我这个常苦于代码调试看不到直观的链表或者数组图的小白可是很大的帮助。
运行模式分两种,静态编译(Visualize Execution)和动态编译(Live Programming Mode),区别在于能不能在演示途中修改代码和改变图形显示设置。
不过各种代码有自身的运行限制,详细见文档讲述。。
工具介绍就是这些,至于使用和优点比较大家看各自的情况选取发挥。对我来讲最好不过就是能看到自己写的代码背后数据的操作过程了,今年还有名为hedis的大佬发布了一个名为data visualizer的vscode插件(https://github.com/hediet/vscode-debug-visualizer),可是涉及的知识要求并不是我能够掌握的。。。。
另外附Dijkstra算法的python实现如下:
from json import dumps graph = {'start': {'a': 6, 'b': 2}, 'a': { 'fin': 1}, 'b': {'a': 3, 'fin': 5}, 'fin': {}} # graph["start"] = {} # graph["start"]["a"] = 6 # graph["start"]["b"] = 2 # print (graph["start"]) # graph["a"] = {} # graph["a"]["fin"]=1 # graph["b"] = {} # graph["b"]["a"]=3 # graph["b"]["fin"]=5 # graph["fin"] = {} # print(graph) infinity = float("inf") costs = {} costs = {"a": 6, "b": 2, "fin": infinity} print(costs) parents = {"a": "start", "b": "start", "fin": None} processed = [] json_graph = dumps(graph) def find_lowest_cost_node(costs): lowest_cost = float("inf") lowest_cost_node = None for node in costs: cost = costs[node] if cost < lowest_cost and node not in processed: lowest_cost = cost lowest_cost_node = node return lowest_cost_node node = find_lowest_cost_node(costs) while node is not None: cost = costs[node] neighbors = graph[node] for n in neighbors.keys(): new_cost = cost + neighbors[n] if costs[n] > new_cost: costs[n] = new_cost parents[n] = node processed.append(node) node = find_lowest_cost_node(costs) print("Cost from the start to each node:") print(costs)