当前位置:   article > 正文

怎样学习数据结构? 伯克利神课CS61B 总结感悟,学习指南和避坑建议

cs61b

目录

【概述】

【课程传送门】

【课程评价】

【课程版本选择】

【课程教材选择】

【课程难度与作业量】

【课程简介】

1)了解数据结构类型

2)根据场景应用数据结构

3)学习了Java这门语言

【如果时光倒流,我再次上这门课时我会注意什么?】

1.读英文原版教材。

2.注重课本,注重一手资料。

3.写作业,要多做题目。

4.坚持。


文章6900字,阅读时间约5分钟

【概述】

学习编程有两门基础课程,即数据结构算法。数据结构中网络公开课中评价一直居高不下的就是UCBerckley的数据结构了。数据结构是CS入门的内功心法。就像九阳神功,掌握了内功心法,张无忌再去学习乾坤大魔移,太极拳法等等就能很快的融会贯通。内功不足直接学一些招式可以很快的看到效果。就像梅超风九阴白骨爪,白蟒鞭法摧心掌名震江湖,但内力不足则后劲不足。但这一门伯克利的Data Structure就相当于上卷的九阳神功,主修内力。虽然修炼需要的时间长,却十分值得。

网上传的帖子“3个月学会JAVA,月薪3000到1万!”,“想要转码,这样刷题就对了!”。“我就是普通人,这样学JAVA,3个月跳槽大厂”。让你忍不住点进去看,有些很坑人。朋友们,在错误的道路上行走,你觉得走得很快,此时快就是慢。学习编程不在于用多久学会了java,python。而是在于在对的路上持续行走,在重要的路上扎实推进。这个时候,慢就是快。幂律法则中提出自然界的一大规律呈现二八分布,成甲在《好好学习》中提到将80%的精力投入到此门技术前20%重要的知识上学习,效率是最高的。而“数据结构”就是编程这门技术的前20%最重要的部分。

CS61B主要用java编写,前面几节课课讲述java的语法和用法。后面开始进入数据结构部分,数组,链表,二叉树,图,搜索,排序。其中一部分 与普林斯顿的神课 Algorithms 有重复部分,但普林斯顿的算法课更深一些,跟注重算法的思想的探究。如果是小白,入门编程,先修这一门是不错的选择。

【课程传送门】

  • 课程名称:CS61B (Data Structures)
  • 课程定位:入门
  • 所在学校:UCB
  • 讲师:Josh Hug
  • 课程链接:https://fa20.datastructur.es/index.html

【课程评价】

  1. 老师幽默风趣,讲课深入浅出。 Josh在伯克利的评价确非常非常的高。他有多受欢迎呢?在reddict上学生对他的抱怨就是 “The only negative thing about Josh Hug is that he doesn't teach every course in which I am enrolled. 我想起大学教我C++的化学老师(没错,我们化院教计算机的也是化学老师),我学的一塌糊涂,就是老师太烂啊。C++语法就讲半个多学期,后面两节课上机直接懵逼。hug是边编程边讲语法概念像扣子一样缝进你的知识体系里。每节课之间的知识点连接得很紧密,循序渐进的深入。我们原来的C++老师是罗列了一对知识晶体摆出来赤果果的给你看让你背。Josh是先放一块晶体,放第二块进去的时候告诉你他们的联系和关系是一条直线,再放下一块,这一块和以前知识晶体的联系是一条波浪线。循序渐进的帮助你搭建出了一个知识体系,告诉你他们的关系呈现三角形。这样的方法让我记的更牢固了。
  2. 教材好。我记得我大学学习必修课C++教材的还是我们大学自己编的,现在看完了《My first Head Java》《Data Structures》《Algorithms 4th》,回头看才发现我们当时学的教材也真tm的烂,学习曲线陡峭的一飞冲天,像我这样资质平庸的人根本就在山脚下倒了。虽然陡峭,但我们可以多好几条路走。我的感受就是遇到不会的概念就去多看几本参考资料,上网找帖子,youtube上搜索相关视频。你可以从多个维度去看待这个概念,这条路陡峭,我们可以选择山后面的梯田啊。你可以将难以理解的概念想象成一片拼图,你拼不进去你的脑海里是因为大脑中没有找到他相邻的拼图(相关的基础的神经回路),但左边突出部分拼不进去,可以去试试右边凹进的形状啊。像hashtable我刚学的时候,觉得好难好抽象,对于其中用到的liner probing 方法说的云里雾里,我就找youtube小连环画的视频,廖雪峰java网站上看读同一个概念的解释,感觉好懂多了。
  3. 注重实践。这门课的作业和项目很棒。

    2020的版本的内容更加丰富,项目有4个,后两个大的project做完后收获很大。一是将A*,Tries,Priority Queue,Map,HashTable 多个数据结构和复杂的搜索算法融合在一起的BearMap。你会实现伯克利校园大小的谷歌地图,完成地图查询,道路搜索,路径指引。 第二个大的project是 设计一个游戏Build your Own World,这个项目不需要fancy的数据结构和算法,主要锻炼你handle比较大的项目的能力。Lab每次任务比较琐粹了,共有13个。 Homwork有两个,一个是basic java synax,一个是Disjoint Set结构的延伸题目。

  4. 完全免费。

【课程版本选择】

本课程有很多版本,如果你想要使用本课程自动评分系统的话,可以选择2018spring的版本跟着学,因为只有这一年的邀请码公开在了github上面。如果你觉得自己就可以写测试代码,推荐你学更近一期的课程。我开始学的是2014年版本,还是在黑板上手输入的那种,环境搭建没有lab支持自己花费了很多的时间。后来发现了2020 Fall版本,因为疫情的大家都是网课,所以在网络上可以找到非常非常全面的资料。关于lab,homework和project每个步骤怎么做非常详细。是我最爱的版本。

【课程教材选择】

开始学习Java的基础的时候,可以看《My First Head Java》,通俗易懂,幽默风趣,就像看小说一样,每天翻几页。后来讲解数据结构的时候,最有效率的课本当然是Josh自己在github是哪个写的课本啦。链接放在这里。老师推荐的看的书是这个Data Structure。看了一段时间Josh自己编的书,学到后面的数据结构的时候就感觉不够用了,讲的比较浅。我就看了红宝书4版《Alogrithms 4th》里面的代码都是用Java实现的,不是伪码,很容易理解。课程的后半段和《算法》课有一部分重叠,我就是看算法4th这本书的。

【课程难度与作业量】

每周大约10小时,3个小时视频可按讲义,4个小时写作业,2-3小时左右看《my first head java》和课程自己变得e-textbook。我是完全小白,什么编程语言都不会,学的比较慢,我用了4个月才学完这一门课。

【课程简介】

上完这门课你会学到什么呢?

1)了解数据结构类型

这门课是用Java学习数据结构。数据结构的存储方式两种“数组”和“链表”。这是数据结构的源头,是数据结构大厦最基础的两块基石。其他的数据结构知识这两种基础数据结构的变种而已。比如说“Stack”,“Queue”可以用链表可以用数组,数组实现就存在扩容的问题,链表实现就需要更多的内存来存放指针。用数组结构实现堆和栈的API我们可以选用ArrayList,用链表实现的话我们可以选用LinkedList。这门课中作业用数组和链表两个数据结构实现双端队列就是一个非常好的作业。

[树]这种结构,用数组来实现就是[堆],一个完全的二叉树;如果用链表实现就是最常见的二叉树,因为不一定是完全二叉树,所以我们需要指针指向子节点。从次延伸出红黑树,KD-Tree(一次很好的大作业),B Tree,BPS Tree(project3随机地图会用到)

[图]这种结构,用数组实现就是邻接矩阵。可以很快速的判断临边。但是如果边比较稀疏的话相对会浪费掉一大部分空间。此时用链表实现,就是邻接链表。虽然效率会慢一些,但节约了大量的空间。

[哈希表] 就是通过一个散列函数将key银蛇到一个大的数组里面。对于解决哈希表冲突的方法,可以用数组结构,也可以用链表结构。lineat probing 法需要数组的特性,占用空间少,只是删除的时候需要重新排序,以便连续寻址。seperate chain法需要链表的特性,同一个key接一个链表,操作简单。但需要而外的空间存储指针。

以上就是这门课中涉及到的数据结构了,或许你会感叹,万事皆是链表啊。这也就是为什么Josh会用两个章节的内容讲解链表吧。

2)根据场景应用数据结构

我们学了数据结构,应用的操作基本就是四个 “增删查改”。所有的数据结构都是根据数据的特性设计,按照最终目的,选择最优的的方式去实现“增删查改”这几项操作的。

如何高效的去增删查改,也就是访问,就是应用数据结构的重点了。

数组是线性结构,他的访问框架:

  1. traverse(int[] arraylist){
  2. for(int i=0; i<arraylist.length; i++){
  3. print(arraylist[i]);
  4. }
  5. }

链表是非线性的结构,访问的框架有两种,一种是用递归,一种是用迭代

  1. class ListNode{
  2. int val;
  3. ListNode next;
  4. }
  5. traverse(ListNode head){//迭代
  6. for(ListNode p= head; p != null; p=p.next){
  7. print(p.val);
  8. }
  9. }
  10. traverse(ListNode head){//递归
  11. if(head == null) return;
  12. print(head.val);
  13. traverse(head.next);
  14. }

我们学习完数组和链表后,就进入了二叉树的学习。可以看到,二叉树的遍历就是典型的非线性的递归结构。因为除了Heap堆这种结构,二叉树的实现我们是用链表实现的。

  1. class TreeNode{
  2. int val;
  3. TreeNode left, right;
  4. }
  5. traverse(TreeNode root){
  6. if(root == null) return;
  7. traverse(root.left);
  8. traverse(root.right);
  9. }

树的遍历的结构就是链表递归遍历的延伸,我们再看一下图的遍历的结构:

  1. class TreeNode{
  2. int val;
  3. TreeNode[] children
  4. }
  5. void traverse(TreeNode root){
  6. if(root == null ) return;
  7. for(TreeNode child : root.children){
  8. travere(child);
  9. }

你有没有发现这个结构特别的眼熟?不就是树遍历的升级版吗?

这套课程的好处就是他是一个自底而上的阶梯型的结构,他不仅仅是介绍了数据结构,也教授了他的应用框架。所谓去leetcode刷题,就是在明白这些框架的基础上,更具题目要求去套用罢了。有了这些框架,你再去学《算法》这门课时,就会感到水到渠成了。动态规划,二分法,回溯这些思想就是在这些框架的基础上的拓展和延伸了。

3)学习了Java这门语言

学习一门新的语言就像叫一个新朋友,想要教好这个朋友,脚要了解朋友的性格。一门语言就是有各种特性组成的。我们常听说Java是编译型语言,Python是解释型语言。那Java又用什么特性呢?

语言1 = [特性1, 特性2, 特性3] 

语言2 = [特性1, 特性2, 特性3] 

比如Java,java = [继承,封装,多态] 我们将一门语言拆分成几个特性去学习,学习效率也随之增高。特别是如果你会了其他的语言的情况下。比如一个在python中的概念Higher Order Function,即函数可以作为参数传入另外一个函数。在Java 8中也可以实现,只是方法上是运用了接口。这样 语言1 + 语言2  = [特性1] 的学习方法,让我们更高效的学习一中心的语言。 比如Java中的Static Type Checking,开始总是觉得很麻烦,因为葡萄红是动态类型的不需要检查。java则要求吧每个类型写得很清楚。慢慢觉得这是Java再帮你减少工作量呢,在程序运行前编译器就代你检查了静态类型,可以从开头就避免许多错误。 

【如果时光倒流,我再次上这门课时我会注意什么?】

1.读英文原版教材。计算机专业书籍的英文词汇绝大多数就是高中词汇水平,只要英文不差,读懂并不难。英文原版教材会让你避免中文翻译的坑,明明很简单的术语,却被翻译得很抽象晦涩。比如说“鲁棒性”,这是个什么鬼?如来是robust的音译,说的是计算机系统就算遇到异常系统也能正常运行,就是“稳健”。 再比如“套接式编程”,看起来很抽象。英文就是socket,就是插座。现实生活中我们插上插座,就实现了电流的传输。计算机世界里programming socket就是插上网络的插座,实现你的程序与网络上另一个程序实现传输。是不是很形象呢?

2.注重课本,注重一手资料。如果我再来一次的话,我会先读一下课本再来带着疑问看视频。开始的时候,我开不注重课本了,导致记得的知识体系很分散。就是看什么都眼熟,连起来就不会用。也就是知识晶体之间的链接没有有效的连接好。josh的这本书是我后来才发现的,真是喜欢啊。Josh很幽默,课上的代码示例也很有意思。我发现我喜欢静静的读书的感觉,大于看视屏的感觉。在阅读中是我有时间去思考,遇到触动的地方,停下来细细回味。逐渐自己觉得好像看书效率更高一些。后来读到学习金字塔理论的事后才知道:

我的听讲的学习方式学习吸收效率才5%,看书的学习效率是10%。我们也可以看到,如果你把每次的作业发布在网站上教授大家,学习吸收率可以达到90%呢。可惜当时偷懒不知道这个以教为学的方法,学过之后,就在懒得输出以前的作业了。

我觉得我以前学习的时候抬不重视课本,喜欢看别人总结,参考书学习走了很多弯路。本质上是我的投机取巧心里吧,但实际上这样弯路更多。因为那些二手资料是别人咀嚼过的支离破碎的。一手资料虽然冗余繁杂,不比二手资料好消化,但也是质量最高的。我会将它想象成一本武侠小说,天下武功唯快不破,引文原版的书就是内功心法,以一招敌万千招式的内功修炼秘籍。我把他放在我最容易看到的地方,睡前翻几页,像读睡前故事一样,我的身体里有一种东西在萌发的感觉。他好像打通了我的奇经八脉,游走全身穴道。我了解到了一切原来皆有链表而来,哈希表是以空间换时间,图就是前面链表哈希表优先队列的集合体啊。

这里分享一个熔断读书法读书的每一张每一节我们不是花同样的精力去看的,遇到让你产生感触的,让你特别以获得就停下来,熔断。去思考,同样的道理还能用到什么地方?回想自己的经历和学识去推导,解释。而不是去简单的复述作者的要点。罗振宇说他学习新知识就像缝扣子,将新内容缝到自己的知识体系上面。所以朋友们,读书最重要不是去复述教学大纲,而是接缝,结合自己的神经回路,运用知识转换的力量,将新概念缝在自己的体系上。我们班大神上课就不记录笔记,我当时还不屑一顾。现在想来,我才是哪个愚蠢的人。人家记录的重点是将新概念用转换的力量将其缝进自己旧的知识体中,逐渐充实自己的知识圈。我只是复述别人的知识框架,并没有装订到我的脑子里。「《刻意练习》一书中提出的一个理论正好可以解释这个现象。我们将知识比作一个圈的话,内圈我们掌握的知识称为舒适区,中圈为拉伸区,外圈为困难区。人的认知是无法跳跃区域发展的,只能在现有的基础上一点一点的向外扩展。」让我们疑惑,触动的地方就是处于我们拉伸区的知识,在这个区域里面学习,我们的进步就是最快的。

3.写作业,要多做题目。学习编程和学数理化不一样,它是一门技术。就像打铁,你不可能通过上课看书就学会打铁的,你只有每天敲敲打打,才能淬炼成一把宝剑。光看不练,是学不会编程的。

4.坚持。这是Josh经常挂在嘴边的一句话。有时候,慢就是快。做第一个lab的时候可能你就会卡很久,当不熟悉编译环境语言语法,很容易挫败。这时候,耐下心来,你要相信慢就是快,一点一点去学习使用git,terminal,熟悉IDEA。我是没有变成背景的,刚开始的时候看public static void main String 觉得好可拍,一个字都不知道是什么。自己的一个体会,就是要给大脑足够的时间去去理解一个东西。有时候你对一个东西看来看去不理解的时候,休息两三天,再回来看突然懂了。我们学新知识就像盖房子砌的一块一块砖,砌好一块糊上水泥粘在我们大脑里,但你得给水泥时间风干啊,才能砌出牢固的强。学习科学需要两个过程,一个是短暂的学习期,专注模式下的‘神经砖块’的垒砌过程,一个是学习期之间的间隔,就是‘思维水泥’的凝固过程。所以,不要着急,不要焦虑。只要方向是正确的,慢就是快。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/243559
推荐阅读
相关标签
  

闽ICP备14008679号