上周(2024 年 12 月 10 日),清华大学的严蔚敏教授去世了,享年 86 岁。
严教授写过《数据结构》大学教材。数据结构是程序员的基础课。据睡在我上铺的郭教授回忆,我在中国科大读书时用的就是严老师的教材。愿严老师安息。
这则消息让我想起了我学习数据结构的几个小故事。
上中学时,我在苹果机上学习了 Basic 语言和 6502 汇编。那时的我,不懂结构化编程为何物,没有面对过对象,不知什么是数据结构,更说不出来它有何用。
无知者最无畏。我认定:一切计算机问题都可以用数组和全局变量解决。如果不行,就上二维数组。
我祖上有位名人,叫万百千。他自小聪颖,三天就学会了写字。
第一天,先生教他写一横,说:“这是一。”
第二天,先生教他写两横,说:“这是二。”
第三天,先生教他写三横,说:“这是三。”
先祖一拍大腿:“我会了!”
先祖的母亲说:“我儿,把你名字写给娘瞧瞧。”
先祖卒。
我就像那位名人老祖,没有意识到“能解决”和“能用合理代价解决”的区别。
后来我上了大学,听高年级的老乡说“数据结构”很有用,就有了了解一下的想法。
我不喜读正儿八经的教材,但对有趣的东西却一拍即合。我在报上读到有一本书叫《数据结构趣谈》,据说通俗易懂,适合我这样的门外汉,便着手采办。
我从科大西区跑到东区,又在合肥最繁华的三孝口和四牌楼来回跑了几趟,书没买到,倒是添了几盘流行音乐的磁带,花光了下个月和下下个月的预算。
为了能吃上饭,我停止了布朗运动,改成写信,请一位在上海读书的女同学代为购买。上海地方大,果然成功了。
读了女同学寄的书,豁然开朗。从此我知道了二叉树的三种遍历法和排队要先进先出的道理,言必称指针。
学成文武艺,货与帝王家。我自学了数据结构的知识,便常去机房逡巡,以图有女同学问我问题。
然而在科大要见到女生已属不易,要她们提问更是千年等一回。要知道我们班的奖学金是长期女生霸榜的。
傻人有傻福,愚公待兔最后还真给我等到了。
一个黄道吉日,我又在机房找了一个女同学边的位置上机。
过了一会儿,女同学托腮沉思,显然是遇到了难题。
我把键盘敲得噼啪响。这叫盲打,知道么?
突然,女同学转向我,发出天问:同学,在 Turbo C 的编辑器里一直向右移动光标最多可以跑多远?
这尼玛超纲了啊!
如果我看过王家卫的《东邪西毒》,此刻或许可以云淡风轻地回答“每个人都会经过这个阶段,见到一个光标,就想知道光标后面是什么。我很想告诉你,可能移过去,你会发觉没什么特别。再移回来,会觉得这边更好”。
但王家卫不能让我在 1991 年看到还没开拍的《东邪西毒》,我也只能在震惊中石化在原地。
答不出女同学问题的耻辱,一直刻在了我的心上,成为我胸口永远的痛。我恨!光标右移有时尽,此恨绵绵无绝期。
这伤痕直到我出国之前一年才被熨平。
那一天,秋日的阳光穿过中科院计算所稀疏的树枝,斑驳地照在南楼紧闭的玻璃窗上,投射出忽明忽暗的图案,让正在调试C++指针的我浮想联翩。
这时系统提示我有邮件。
朋友们,这可是 1996 年,香港还是英国的殖民地,克林顿还在竞选连任,全世界不会有5个人会想到给我发邮件,有电子信是一件大事,抵得万金油一盒。
我打开邮箱看标题,是一位先一步去美国的女同学的email。
我确认背后无人,才打开邮件。
这位女同学得了美国教育的真传,跳过了对伟大友谊的回顾,开门见山进入主题:她有一道数据结构作业不会做,想要 wen wen 我。
这道题要求用线性时间判定一个单向链表是否有环。
五年之后,我看到了这道题的聪明解法:用两个指针 p 和 q 同时从头遍历这个链表,但是它们前进的速度不一样,p 每走一步,q 要走两步。如果 p 和 q 在某一步又碰面了,就说明有环。如果 q 走到链尾也没有重逢,就是没环。如果链表有 N 个节点,最多迭代 N 次就会有结论,所以是线性时间复杂度。
但我不是大聪明,发明不了这个算法。那时候也没有谷歌雅虎,连在实验室用 telnet 和 http 都是要罚款的,因为网络带宽是稀缺资源,1KB 要两毛钱人民币。
但我一心要一雪前耻,冥思苦想数小时,终于在没有算法的地方想出了一个算法,赶在女同学的 deadline 前做完了作业。
我的算法也是从头开始遍历链表,但只用一个指针,一边遍历一边将链表翻转,也就是说遍历到节点 n 时,顺手把从 n 到后续节点 m 的指针改成从 m 到 n。如果遍历结束时能回到起点,就说明有环,否则就没有环。进一步分析表明,要是链表里有 N 个节点,不超过 2N 步就会结束,所以时间复杂度也是线性的。
只是,我的算法有一个问题:它不是无损的。跑完算法后链表被翻了个个儿,不再是原来的链表。
但不怕,我有补救的办法。
东东枪老师的六里庄人民广播电台有个广受欢迎的栏目“房中有术”,专门介绍夫妻生活小常识。第一期房中有术节目送给大家的是一个冷知识:酒后行房,颠倒五脏,所以酒后不能行房。
但是有人问了:如果酒后偏要行房,就要行房,不得不行房,又该怎么办呢?
对此枪老师有一个妙方:酒后行房,颠倒五脏。那么行过之后再行一次,不就把颠倒后的五脏又再颠倒回来了吗?
对于链表环的判定算法,我独立于枪老师提出了类似的解法,那就是把链表翻转之后再翻转一次,链表不就还原了吗?
当然,万氏双翻法效率堪忧,虽然满足线性时间复杂度的要求,但操作步数比起聪明解法要多很多,实用性稍逊。
不过,这是我自己发明的算法,必须敝帚自珍。
等我到了美国,读完书工作了,在我歌面试程序员时数据结构是必考的,这门基础课也就长期驻留内存。
现在学习数据结构的条件比我们那时候不知强了多少倍,有 LeetCode 可以刷题,有 GPT 可以答疑,那道曾经难倒科大女生的算法题,只能算是入门级了。
只是塞翁得马,焉知非祸。学习上不求人了,跟女同学套瓷的机会就少了许多,不知拆散了多少好姻缘。琼瑶阿姨地下有知,一定会对成功刷题上岸的男同学讲:
葛革你好无知好肤浅好愚昧,你得到的不过是百万年薪,可你失去的却是美眉的爱情啊!
0
推荐