实践才有收获——《数据结构与算法分析》学习感悟

收获:

数据结构这门课程,我在本科大二的时候就已经修过了。当时无论是链表,栈,队列,还是二叉树。都是有学习过的。甚至连图论的Dijkstra算法,霍夫曼编码。都是考试的重点。当时是如何学习的呢?

看懂算法实现的步奏,会在纸上画图。不要求编码实现!

虽然说当时由于课程紧张,这样做无可厚非,但是,这样学习的来的数据结构,完全就是停在之上的,并且没有深刻理解其内涵。所以考试一结束,我很快就忘干净了。而且,当时特别害怕Dijkstra算法与霍夫曼编码,觉得特别难。

现在亲手实现了《数据结构与算法分析》一书上所有的数据结构与算法之后。在第十二章中遇到霍夫曼编码,感觉都没有必要浪费时间了。对于以前的最害怕的Dijkstra算法,还可以自由使用二叉堆或者是斐波那契堆来实现。连图论中的邻接表也是自行实现的。而且感觉Dijkstra算法不过是入门级别而已。对于图论的算法已经完全不害怕了。

现在,无论对于任何一个算法,我已经能很快利用所学的知识来选择合适的数据结构,并且分析出算法的复杂度,找到最坏情况。感觉算法对我来说, 已经不再有任何困难了。

学习历程:

一、纯新手:

链表,队列,栈:

因为本科的时候已经学习过了,所以在实现这几个数据结构的时候,没有怎么看书,直接按照以前的记忆去实现的,结果到处出错。比如删除时链表断裂,又或者是队列的逻辑出错。

好不容易实现完链表形式的队列,遇上数组形成的栈和队列,又不知道怎么去实现了。原因还是对于这些结构的理解不够深刻。另外就是实现算法时,不熟悉一些常用的处理技巧,遇到一点点困难就不知所措了。

最后这些算法的实现,还是通过模仿书上的代码完成的。并且也没有写测试历程。结果再后面再使用的时候,发现出了很多错误,然后又重新修改正确。

二、略有感悟:

二叉树、散列、优先队列

在实现二叉树的时候,就开始理解一堆typedef的作用了,也开始理解为什么数据结构的定义上要添加这么多奇奇怪怪的typedef了。对于如何写一个数据结构,总算是有一点点的理解了。

在二叉树的插入与删除算法中,大量的使用了递归。最开始完全不能理解是一个怎样的插入过程。直到不断地编码,不断地调试,突然一下就彻底理解了递归,然后,无论是递归代码改成非递归,或者是非递归代码改成递归,对我来说都是轻而易举了。

理解了递归之后,开始实现AVL树,在这里遇上了第一个真正的难题,SplayTree,伸展树。

《数据结构与算法分析》书上给出了伸展树自底向上的旋转方式,但是没有给出任何的实现代码。整个的编码需要我从0开始。最初,我的想法是使用递归的方式,自顶向下遍历,然后出栈的时候实现旋转。思考了一下,发现这种方式不太靠谱。然后开始在网上寻找别人的博客学习。

首先发现自底向上的实现都是带有父亲节点。于是,先自行实现了带有父亲节点的伸展树。不得不说,每增加一个指针,编码就更容易出错一倍。在带有父亲指针的旋转代码上,花了我非常多的功夫去调试。不过总之,最后是自行实现了这棵树,并且没有参考别人的代码。

然后是根据别人的博客,学习明白了如何自顶向下实现伸展树,又自行实现了一遍。

这个时候,对于自己实现一个数据结构已经有了不少自信了。

其后,散列,优先队列,都没有遇到特别大的麻烦,基本上是理解明白了书上的过程,实现的时候最多在比较麻烦的地方再参考一下课本。

三、自行寻找解决办法:

在学习到第九章,图论之后,基本上基础简单的算法就学完了。图论的第一个难题是图的表示。书上没有给出任何代码,自行学习玩邻接表的概念,然后参考了网上别人的实现,使用自己以前实现的哈希表之上,完成了邻接表的实现。并且使用该邻接表完成了后续所有的图论算法。

最大网络流问题:这个问题也是书上只给出了算法的流程。只有几张示例图片,根据这个流程,自行实现了最大网络流问题。

图论中最麻烦的是欧拉回路问题。欧拉回路问题基本上连图都没有给出。只用文字描述一下算法,然后提出,可以在O(E+V)时间内完成算法。

最开始的时候,完全不明白该怎么做,寻找别人的博客也没有找到合适的博客。只能自己硬着头皮上了。第一个版本,实现了功能,但是算法复杂度为O(E*V),然后自己不断的寻找改进方法,最后改进到了O(E+V),这个过程我写了一篇博客,大家可以去查看我修改的详细过程。

四、通过英文文献实现算法:

实现了第四个提升之后,我感觉我的算法和数据结构上应该是一点问题也没有了。这第四个提升,就是在实现自顶向下的红黑树时,所学习到的。

课本上给出的红黑树,是使用自顶向下的方式实现的,不过它只给出了插入的情况,最复杂的删除基本等于没说。我在网络上寻找到的博客中,没有人使用自顶向下的实现方式,就连July的博客,算法导论中,都是使用的自底向上的方式,并且多使用了一个父亲指针。

在这种情况下,我最终找到了一篇英文的文献,其中叙述了自顶向下删除中会遇到的情况,然后需要如何旋转变换。不过没有流程图,也没有伪代码。

在学习明白之后,自行画出了流程图和伪代码。然后实现了自顶向下的红黑树,并且再学习了自底向上的红黑树的实现,并对他们做了一个对比。

感悟:

编程这门学问,还是得靠练习。就好比我之前学习C++,都学习在了纸上,结果再使用的时候,还是得再翻书,因为压根没有学习进去。所以现在看来,我之前学习的UNP最后几章,还得花时间去编码实现一次。才能有一个更加深刻的理解。



你可能感兴趣的:(实践才有收获——《数据结构与算法分析》学习感悟)