关于技术与工作

   
    从来不写笔记的我为什么突然想写笔记?最近不知道是怎么回事?感觉自己的记性非常不好,比如接触了一个新东西,就算了解了其实现原理,能跟着思路自己手动完成,但是不过一个星期又忘了?难道是自己老了?从前找东西都是找的度娘,就算是使用过的东西也是同样的找度娘?记性是真的很差。所以现在想把最近所学的东西归纳总结一下,就算忘记了也能不断的通过笔记来复习,都说好记性不如好键盘,最近在学习数据结构,想把数据结构做一个总结,这个只是个人的总结,大牛路过的路望指点其中的不足,作为一名小白我只想把所学的东西做一个记录。

你曾经充满热情,是一位开源软件倡导者,你崇尚全栈工程师才有未来的理念,你渴望改变世界。但是现在你每天都处于焦虑之中,你每天不断地学习各种技术Kotlin、Swift、React
Native、RxJava、hybrid思想等等等各种新技术,只有你在微博转发各种新技术文章的时候你才稍微轻松一些,这样会让你觉得不至于被快速发展的技术抛到后头。

我觉得,技术与工作最理想的结合状态是,自己能学习到新的技术,这些技术也能应用到工作中;工作的内容又不那么枯燥,都那么具有挑战性。

一、为什么要学习数据结构?

图片 1

程序员的工作首先应该是富有挑战性的

有这么一句名言:

工作,它之所以成为工作,是因为你只需要工作而不需要思考。

你也许会对这句话有异议,但是大部分人和大部分工作确实是这样的。工厂员工在流水线上机械地组装,服务员每天重复着招待客人,厨师日复一日地烹制菜肴,等等。工作,就是人和机器之间的中间层,等到某一天机器人有这种功能了,人自然就不用工作了。

但是我觉得,如果你在工作中比别人多那么一点思考,也许你就会出类拔萃,程序员这份工作就是这样。我认为,程序员的工作首先应该是富有挑战性
的。但是我见到很多国内的程序员,只是项目完了接着下一个项目,代码重复了一遍又一遍……也许知道代码有问题要重构,系统架构不好要改进,可是没那么多时
间啊,天天加班干活,项目时间紧迫。就这么恶性循环,就应了那句话:你说你有5年工作经验,但在我眼里,你不过是将一年的工作经验重复了5年。

程序员的工作是富有挑战性的,但是这个是在国外,在国内,很少真的有程序员,能做到程序结伴,不断挑战新的高度。大多数是年轻的时候努力奋斗了
几年,到后来,因为本方向的发展空间不是很大了,但是又不能跳转到其他的方向,怎么办呢,带几个新人吧,这样也有点领导的性质了。但是,有没有想过,大学
研究生读了这么多年,工作写了这么多代码,突然有一天不写了,转做项目管理了。这也就是中国的IT的现状,工作几年之后大家都痛苦地抛弃了代码,抛弃了自
己以前的很多代码积累。

        举个例子来说,在古代为什么我们看的武侠电视剧里面的人在修炼武功的时候都要先练习基本功?就像少林寺和尚为什么进门之前要先挑水劈柴念经,为的就是修炼内功,只有修炼好了内功才能在高阶武功上进行深造,一步一步的达到上层。这就是为什么一天屠龙记的周芷若在内功不扎实的情况下修炼九阴真经达不到上层的原因。作为一个程序员,我们学习数据结构的目的就是为了打好基本功,只有这样一步一个脚印的走下去才能达到高级工程师的水平。而且在大型公司面试的时候基本都要求会数据结构,因为我们的程序就是数据结构和算法组成的,所以其研究价值比较高。

你开始在知乎上提问:

程序员的工作与赚钱

我们出去工作,说到底,最根本的目的就是赚钱。但是,我们不能因为赚钱,而丢弃自己的信仰。

先来来看看这个一个故事吧:图片 2

照片上那个戴墨镜的哥们, 叫 Nicholas McGuire,
是兰州大学的客座教授。看到这个照片,和我一样,一定有无数多的问题,
我一个一个帮你问,然后解答吧。

  • 你可能会奇怪,这么郑重的场合, 他为什么戴墨镜? 耍酷吗 ?
  • 答:其实不是耍酷,Nicholas 其实是一个半盲人。

  • 别人都是西装,他为什么只有衬衣 ?耍酷吗?
  • 答:其实不是耍酷, Nicholas
    真的没有西装,他穿的那身,是他能找到的最好的衣服。

  • 他到兰州大学研究什么的? 是研究戈壁生态,
    还是沙漠治理,还是兰州拉面 ?
  • 答:其实都不是,他研究开源的嵌入式实时操作系统——RTLinux,
    以及与此相关的一切开源软件以及嵌入式系统,是 RTLinux 的内核代码管理员之一,不折不扣的高科技。

  • 他是兰州大学高薪聘请来的吗?
  • 答:没有高薪,事实上,一直连薪水都没有,直到今年,才申请了一些。

  • 他是不是每年来兰州一两个月,就当是度假?
  • 答:不是,他实实在在在兰州大学呆 10 个月, 只有 2
    个月回德国老家度假。

  • 他是不是只这样做了 1 两年.
  • 答: 不是,他从 2005 年开始,直到现在,一直这样。

  • 他图什么 ?
  • 答: 因为兰州大学有一个叫周庆国的老师以及小组, 不停地向 RTLinux
    的内核提交代码。他去兰州大学,就是要和他们一起工作

  • 兰州大学的学生英语如何?能和他一起工作吗?
  • 答: 他和兰州大学的学生,
    无论是生活都是开会还是写文档,通通遵循开源社区的标准,
    用英语交流,木有问题。

  • 为什么选择兰州大学?
  • 答:因为兰州大学有一个叫周庆国的老师以及小组, 不停地向 RTLinux
    的内核提交代码。

  • 周庆国老师拿到过国家项目的资助吗?比如发展开源软件基金,红旗 linux
    神马滴。
  • 答:几乎没有,兰州地处西部,离北京很远,拿到项目很难,他能作的就是不停地研究代码,提交代码,向开源社区贡献代码。

  • 这个与赛灵思有神马关系?
  • 答: 当他听说赛灵思的在 ZYNQ 的 QEMU 模型上跑的开源 Linux
    内核推出了,并且发布在 wiki.xilinx.com
    上,立即就开始下载研究,跑起来,
    即没有要项目经费,也没有要资助和捐赠,因为在开源人的眼里——无论是开源软件还是开源硬件,开源就象信仰一样,无需证明

看完这个故事有什么感想吗?

不是每一个程序员都要成为比尔·盖茨,都要建立商业帝国成为世界首富。也不是每一个程序员都要做马化腾,建立QQ帝国君临天下。但是我觉得,每
个程序员都应该向Dennis
Ritchie(C语言之父)学习,在贝尔实验室默默为计算机界奋斗一生。每个程序员都应该向Linus
Torvalds学习,写出改变计算机世界的Linux但却不争名夺利。比尔·盖茨、马化腾是IT商业化的代表,而Dennis
Ritchie和Linus Torvalds则是计算机界学者的先驱。

台湾作家龙应台说了这么一句话:你可以选择做官,你也可以选择挣钱,但你不能选择通过做官来挣钱。

同样的,对程序员而言,你可以选择研究技术,也可以选择赚钱。但是以赚钱的心态去做程序员,那么你也许会品尝不到技术的很多快乐。程序员是一个
职业,一个专业的职业,那么作为一个程序员应该有一个专业上的目标,赚多少钱和程序员的专业素养没有关系,你可以把赚多少钱开宝马作为人生的目标,但是你
作为程序员的目标不应该是赚钱。可以这么说,现在行业内的程序员很多都不是真正的程序员,对那些做着程序员工作的代码工人来说,程序员只是一个混口饭吃的
工作而已,那么工作的目的就是赚钱,盯着钱看就没什么不对了。人生目标和自己的专业目标分不清楚,难怪哪头都讨不到好。专业和职业是两码事,专业关注的是
你做事的能力,职业关系的是你在公司的职位,这个东西理不清楚就只能是两头不讨好。真正的程序员应该是个热爱技术的Geek,喜欢创造与挑战,享受技术带
来的喜悦与创造带来的成就感,而非不断编写着一遍又一遍重复code的码农。

作为程序员应该追求的是自己专业素养上的提升,作为一个职员应该向着高薪努力,当然有的程序员自己又是老板,比如康盛创想的戴志康
,那么作为老板又有另外的追求了。我觉得作为一个程序员,在一个程序员的社区里应该关注的是自己的专业而不是在这里大谈程序员怎么怎么赚不到钱。

也许,每一个程序员在开始的时候都想过要写出非常牛逼的程序,做个人人崇拜的高手,直到有一天,他发现他的代码并不能改变世界的时候,就会向现实屈服,甚至抛弃往昔自己喜欢的编程。

与程序打交道,是我们选择的工作,也是我们选择的职业。程序员,应该是一个值得骄傲的称号,而非是码农的代名词。走出浮躁的泥沼,我们会找到另外一个不同的自己。

学会享受学习过程的乐趣

学习是一辈子的事情,对于程序员来说更是如此,所以如果没有学会享受学习过程的乐趣,那么学习将会是你人生的一个重压。

以学习数据结构为例。大家都知道,对于程序员而言,数据结构是基础,是必须学会的课程。但是现在很多语言,细节都封装得很好,比如
Java、.Net、PHP,几乎都不需要你用到多少数据结构与算法的知识,以致于很多人觉得,我就不会数据结构,我还不一样好好工作吗?这就是浮躁的开
始了。

的确,对大部分程序员来说,工作上很多时候不需要用到数据结构。但是你会发现,工作若干年后,你的技术水平会停滞不前,做的东西总是CURD,
再加上一点设计模式,再者可能有NoSQL、memcache之类的应用。但是,当你写这些代码写到疲软的时候,你会发现这些都是应用层面的东西,别人做
好的现成的东西,到你想理解它们底层与原理的时候,没有数据结构与算法的知识支撑,你会很吃力。勿在浮沙筑高台,尽管你开源软件用得多好,如果不去理解计
算机的底层,顶多也就是个高级点的码农。

要走出浮躁的泥沼,只要理解一句话就行:

学习的真正乐趣不是因为它有用,而是因为学习的过程本身有趣。

所以你需要去发现学习过程有哪些乐趣,还是拿数据结构的学习为例。

1.
数据结构的学习在短期内不会对工作有什么效果,但它是对未来以及自己的投资。学习它你一定不要浮躁,不要觉得它短期内收益不大就不去学习。摒弃浮躁的第一步就是,不要带着功利的眼光去学习。

2.
数据结构的学习几乎都是从线性表开始,然后讲到最重要的单链表。单链表的基本操作就建表、插入、删除、查找等,如果你把这些操作都学完了,是不是该立即进
入堆栈的学习呢?我的建议是,不。“学习”是一个实际上不应该分割的词汇,只有“学”没有“习”将必然导致肤浅。当学完单链表的基本操作,你需要做更多的
“习”。这时候你需要尝试着研究下面的问题:单链表的逆序、求单链表的倒数第N个元素、单链表的排序、单链表的环……等等。当你对单链表的学习进入某种境
界,才进入堆栈的学习,这样你的单链表就很扎实,同时学习堆栈也会变得很有效率。你可以参考我之前所做的专题:《数据结构物语卷二》

千万不要觉得这很浪费时间。左学点右学点,散沙式的学习才浪费时间,连续的思考才是高效的。

3.
享受思考的乐趣。数据结构一开始学也许你会觉得有点难,比如插入一个数据都要涉及几个结点的地址操作,但是当你思考并完全理解为什么这么做,你会有一种豁
然开朗的感觉。并且更重要的是,每解决一个单链表的问题,就相当于做了一次思维训练。思维训练做得多了,对单链表的理解就更深了,以后解决问题就更快。我
们可以这么认为,每做一次思维训练,都能够使我们的思维加速,使我们的大脑加速。为什么牛人一看问题就能知道如何解决?很简单,因为他做过普通人无法想象
的大量的思维训练,正如巴菲特7岁就开始拜师学投资一样。没有人天生就是大牛,对吧?

4.
关于学习的欲望。很多人心里知道,我要学习,但是总是容易被分心。一会看看微博,一会折腾下其它什么东西,结果半天还没看得进一点东西。不要假学习,不要为不学习找理由,没钱?没时间?累?只要你内心坚定且欲望强烈,就会主动学习。

可以看看这篇文章:另外八小时,用辛勤换幸福。如果能把写博当作是一种放松,如果能把写博当作一种享受,不带任何功利的杂质,那么你就会非常强烈地想去写博。(对我来说,写博就是学习)

你可以尝试下早上6点半起来,学习一个小时再去上班,效果很好。这篇文章就是我早上6点多开始写的。学习大部分时间是一个人的活动,难免会有孤独感,当你精力高度集中时,孤独感会减少。当你全神贯注的时候,甚至会感到身心愉悦。“耐得寂寞不寂寞,耐不住寂寞反寂寞。”

5.
不要被厚厚的书吓住。有的人也许会说,你看,数据结构那么多章节,你光单链表这一章就做了一百多个练习,花了一两个月,什么时候才能看得完啊?我说,学习
没人逼你进度,随意看,什么时候觉得自己精通了再转入下一个学习阶段。过早地进入下一个阶段只会让你过早地忘记前面的知识,比如草草地看了单链表的基本操
作,就去学堆栈,过一个星期我问你单链表的反转,你也许就会一时想不出。所以我认为:

坚持做一件事,直到达到一个境界——至于是什么境界,我不知道,你才知道——然后才开始做另外一件事。

6.
你对学习有如饥似渴的感觉吗?对待学习,我很推崇完美主义。比如单链表的基本操作弄懂了,写程序过了一遍,然后开始研究它的各种常见操作。都研究完了,开
始研究比较少见的操作,带头结点与不带头结点的都要过一遍。然后翻遍互联网,看看有没自己疏漏的。发现有疏漏的,你会很高兴,马上再写程序自己过一遍。直
到Google搜索“单链表”前100页的结果你都能马上知道什么回事,知道怎么做,嗯,那就差不多了。

很疯狂吗?在常人看来也许是。但是对我们自己来说,不这么做,很难达到某种境界,或者说,精通。对知识的如饥似渴的时候,当得到新的发现新的知识,你会得到很大的满足感,而且一路走来的成就感,也是对你之前努力的最大回报。

那么,从现在开始,逃离浮躁的泥沼,享受学习过程的乐趣。

文/Veda 原型

二、什么是数据结构?

  • “意识到了自己没有办法成为 top 1%
    的程序员,还应该选择程序员的道路么?”

  • “作为一个帝都码农,现在的处境很迷茫,不知道未来在哪里,我该怎么办?”


  • 能力不如自己的同事创业拿了五千万投资,我是不是应该也出去创业?很迷茫!!”

        数据结构是对在计算机内存中的数据的一种安排。也可以理解为对计算机运算的数据单元的一个抽象。很抽象对不对,反正当初我在学习的时候是没听懂这个是什么意思,但是如果我自己来理解的话,我觉得就是数据与数据之间存在的一种关系,是我们的数据在计算机中的模型。

你说你在bat搬砖,毕业两年年薪50万,你说你买不起房,买不起车,没法改变世界!你很迷茫!!

三、数据结构研究的内容

你说你马上奔三了,身边很多朋友已经创业成功卖掉公司抱着美女开始环游世界了,而你还在某个大厂做小项目负责人,没法财务自由,没法改变世界!你很迷茫!!

(一)数据的逻辑结构

你每天看36kr、看虎嗅、看李开复徐小平的心灵鸡汤,你说你的点子值十个亿但是投资人都瞎了眼,连00后都已经拿到投资了,而你还在写代码,你说你这样无法实现财务自由,无法改变世界,你很迷茫!!

            1. 集合结构

写代码越久你抱怨越多,你脾气越来越大耐心越来越少,你发现你精力越来越不如年轻人,也慢慢听不懂年轻人谈论的技术了,你开始坚信PHP是世界上最好的语言了,毕竟你已经听不懂新世界的语言了,你终于开始不再迷茫。

                    数据结构中的元素之间除了”同属一个集合”
的相互关系外,别无其他关系。

前面的所有吐槽都能在身边找到例子,现在整个技术圈已经浮躁不堪。其实程序员圈子的浮躁是被创业圈传染过来的,但凡工作两三年的都会发现自己身边有不少同学朋友同事拿了不少融资出来创业,而且去年整个创业圈都在炒作90后创业家,这会给我们不知不觉中造成一种错觉,虽然拿着很高的薪水但是总是感觉自己落后了不少。除了被创业圈传染之外,这两年技术飞快发展也给不少程序员造成不少压力,以至于有人问出“意识到了自己没有办法成为
top 1% 的程序员,还应该选择程序员的道路么?”这样的问题。(继续更新中)

            2. 线性结构

我自己觉得要应对以上的焦虑和迷茫最重要的是做好以下几点:

                    数据结构中的元素存在一对一的相互关系;

1、认识到自己的定位

            3. 树形结构

  • 只有少数人才能成为top 1%
    的程序员,接受自己和大部分人一样只能成为一个平庸的程序员而已;
  • 创业和top 1%
    程序员一样,不但需要天赋更需要机遇、自身资源、更多努力,接受自己可能一辈子只能默默无闻上班;

                    数据结构中的元素存在一对多的相互关系;

            4. 图形结构

2、给自己立一个短期的目标

                数据结构中的元素存在多对多的相互关系

  • 比如在某段时间内把某个技术研究通透,且将心得分享出来;
  • 比如利用业余时间写一个自己计划已久的App、网站、轮子等;

    光看这几个名词我们是不太明白它是什么东西的,接下来上图就好理解了。

图片 3

3、给自己立一个长期目标

    根据我们的理解和认知我们大概可以从上图了解到数据结构是个什么东西了。

  • 比如进BAT;
  • 比如去健身房把身材保持好;
  • 比如技术移民;

(二)数据结构的存储结构(物理结构)

            1. 表    

我不是在给你的梦想泼冷水,只是想跟大家说我们除了仰望星空也要脚踏实地,并不是每一个人都会有幸成为马云马化腾,如果万一我们真的是一个平凡的人也要勇于接受这样的自己。之前和西乔聊过一次,收获良多,她和他夫君几年前去加拿大念设计,现在两个人在加拿大全职认真做着“神秘的程序员们”这个公众号,她说他们两是把这个当作一项事业来做,这点对我触动很大,我想我们不一定非要做成多么牛逼的事,成为多么牛逼的人,认认真真做好一件事情足矣。

            2.堆栈

备注:一些和本文有关联的文章:
西乔:我在过着很奢侈的生活
西乔的新出发:去往墙外
作为一个帝都码农,现在的处境很迷茫,不知道未来在哪里,我该怎么办?

            3.队列

            4.数组

            5.树

            6.图

四、线性表

对于表我们重点来研究线性表,什么是线性表?

由零个或多个数据元素组成的有限序列。线性表属于数据结构中逻辑结构中的线性结构。

注意:

(1)线性表是一个序列。

(2)0个元素构成的线性表是空表。

(3)线性表中的第一个元素无前驱,最后一个元素无后继,其他元素有且只有一个前驱和后继。

(4)线性表是有长度的,其长度就是元素个数,且线性表的元素个数是有限的,也就是说,线性表的长度是有限的。

线性表是线性结构的一种,那么线性表当然也有物理结构,也就是说,线性表有两种,分别是顺序结构的线性表(叫做顺序表)和链式结构的线性表(叫做链表)。

(一)顺序存储方式的线性表——顺序表

顺序表是指顺序存储结构的线性表,指的是用一段地址连续的存储单元依次存储线性表的数据元素。

顺序表表现在物理内存中,也就是物理上的存储方式,事实上就是在内存中找个初始地址,然后通过占位的形式,把一定的内存空间给占了,然后把相同数据类型的数据元素依次放在这块空地中。注意,这块物理内存的地址空间是连续的。举个例子来说就是“一个萝卜一个坑”、“排队”等表现形式。如下图:

![]()

知道了表现形式后,我们可以对着顺序表进行分析。如下图:

![]()

我们对线性表上的元素是这样定义的,其中a1是a2的前驱,ai+1是ai的后继,an没有后继,a1没有前驱。n为顺序表中元素的个数,当n==0时,线性表为空表。

顺序表的数据结构的代码表现形式为:

class Student{

Student[] data;

int size;

}

顺序表的应用:

ArrayList,Vector,ArrayQueue,ArrayDeque,PriorityQueue。

并发包:CopyOnWriteArrayList、ArrayBlockingQueue、PriorityBlockingQueue等。

(一)链式存储方式的线性表——链表

链表的特点是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的。如下图:

![]()

链表的分类:

1.单向链表

![]()

2.单向循环链表

将单链表中的终端结点的指针由空指针指向头结点,这样一来就使整个单链表形成了一个环,这种头尾相连的单链表称为单向循环链表,简称循环链表。

![]()

3.双向链表

![]()

4.双向循环链表

双向循环列表是单向循环链表的每个结点中,在设置一个指向其前驱结点的指针域,这样两个单向循环链表就构成了双向循环链表。

![]()

单向链表的数据结构的代码表现形式为:

class Node{

Object data;    //元素  数据域

Node next;      //指向当前节点的下一个元素结点

}

双向链表的数据结构的代码表现形式为:

class Node{

Object data;    //元素  数据域

Node prev;      //指向当前节点的上一个节点

Node next;      //指向当前节点的下一个节点

}

单链表的应用:MessageQueue、LinkedBlockingQueue(并发包)。

双链表的应用:LinkedList、LinkedBlockingDeque(并发包)。