作者:解学武
一文彻底搞懂数据结构(写给初学者的干货)
数据结构是计算机专业的基础课程,是所有程序员的必修课。如果把编程语言比作程序员的剑法招式,那么数据结构就是程序员的内功心法。不懂数据结构就是写代码的农民,了解数据结构才能成为行业专家。
刚刚接触数据结构,初学者肯定有一肚子的疑问,比如:
在这篇文章中,我不会深入讲解数据结构中的某个知识点,而是要揭开数据结构的面纱,让大家从整体上对数据结构有一个清晰的认知,致力于帮助读者快速入门数据结构。
程序运行过程中用到的数据,全部位于计算机的内存中。所有数据在内存中的存储状态,比如是集中存放还是分散存放,需要开发者提前做好规划,而这就属于数据结构的研究范畴。
说白了,数据结构是一门研究如何存储数据的学科。
有读者可能会问,存数据还需要研究吗,少量的数据用变量(对象)存储,大量的数据用数组存储,不就行了吗?答案是否定的,接下来通过一个实例展开讲解。
![道路分布图](/uploads/allimg/240819/2-240Q9112Z01W.gif)
图 1 道路分布图
图 1 是一张道路分布图,记录着 V1、V2、V3 和 V4 之间的道路分布,比如 V1 可以直达 V2 和 V3,V3 可以直达 V4,V4 可以直达 V1。图中的每条路都是单行路,比如 V1 可以直达 V2,但 V2 无法到达 V1。
试想一下,如果编写一个道路管理系统,如何将图 1 中的道路信息存储到内存中呢?首先,要想将图 1 存储到内存中,我们需要存储的内容包括:
将以上两份数据都存储到内存中,就成功的将图 1 存储到了内存里。
如果读者尚未学习数据结构,很可能想不出可行的存储方案。反之如果学过数据结构,这个问题很容易解决,因为数据结构中专门讨论了图 1 这类数据的存储方案,将这类存储方案统称为“图”。
例如,下图是数据结构中的一种存储方案,叫做邻接表,它是图的存储方案之一:
![邻接表存储结构](/uploads/allimg/240819/2-240Q91214204D.gif)
图 2 邻接表存储结构
图 2 中,左侧是一个数组,用于存储 4 个地点;每一行是一个链表,用来存储地点之间的道路信息。如下图所示:
![邻接表存储道路信息](/uploads/allimg/240819/2-240Q912152JW.gif)
图 3 邻接表存储道路信息
数组下标 0 的位置存储的是 V1,后续箭头指向的 2 也是数组下标,由此找到了 V3,说明 V1 能直达 V3;同理,通过后续箭头指向的数组下标 1,说明 V1 能直达 V2。
类似图 3 这种稍复杂的存储方案,除非系统地学习数据结构,否则是不容易想到的。
学习数据结构,就是学习各种数据的存储方案。对于同一份数据,存储方案通常有很多种,选择好的存储方案,后续编码过程中可以更高效地使用内存中的数据,为后续编码提供便利,大幅提高开发效率。
这里给读者分享一张我精心整理的思维导图,图中罗列了数据结构几乎所有的知识点(猛击这里查看超清大图):
![数据结构思维导图](/uploads/allimg/240819/2-240Q9123605Z7.gif)
图 4 数据结构思维导图
注意,我说的是熟练掌握一门编程语言。以 C 语言为例,所谓数量掌握,最简单的衡量标准是能够独立编写一下小项目,比如学生信息管理系统、贪吃蛇游戏、推箱子游戏等。
很多读者觉得数据结构难,实际上因为编程基础薄弱导致的。举个简单的例子,有些初学者能够理解数据结构中存储数据的思想,但就是不会编码实现,这就是典型的编程基础薄弱,编程语言掌握地不熟练。
和视频教程相比,文字教程有一个与生俱来的优势,就是能快速回顾之前所学的知识。学习数据结构,你会接触到很多存储数据的新思路,如果不经常回顾,很容易会遗忘。文字教程和视频教程相互搭配,学习数据结构会事半功倍。
此外学习数据结构的过程中,做以下两件事可以提高自己的学习质量:
手绘数据的存储状态,对学习数据结构非常有帮助。举一个简单的例子,如果我们想象不到链表是怎样存储数据的,可以尝试动手画一个链表,如图 1 所示:
![链表](/uploads/allimg/240819/2-240Q912495W55.gif)
图 5 链表
在这张图中,链表的头指针、各个结点的存储状态都一目了然。通过画图,可以加深我们对各个存储结构的认知,对编写程序实现各个存储结构有莫大的帮助。
那么,数据结构真的无用吗?当然不是。作为计算机专业最重要的必修学科之一,计算机专业考研的必考知识,以及众多 IT 公司笔、面试的侧重考点,仅仅这些光环,就足以说明学习数据结构的重要性。
毋庸置疑,数据结构不仅有用,更应该是每个程序员必须掌握的基本功。
具体来讲,对于同一个问题,数据结构往往会教给我们不只一种解决思路。举个例子,假设我们需要从众多数据中查找出符合要求的元素,多数人就只能借助数组这种简单的存储结构来实现,而通过学习数据结构我们会知道,解决此类问题既可以通过构建二叉排序树、平衡二叉树、甚至红黑树、B+/B- 树来解决,还可以借助哈希表解决。
再举一个例子,几乎所有的编程语言中都提供有数组这种存储结构,但如果没学过数据结构,就绝不会想到,数组还能以链表的形式使用(也就是静态链表,后续章节会做详细讲解)。
事实上,数据结构也有众多编程语言无法比肩的优势。无论是 Java、Python、C++、PHP 还是其他编程语言,无时无刻不在更新迭代,而数据结构却永远不会过时,其包含的存储数据的思想,已经近乎将所有可能的情况都囊括其中,能解决 99% 的实际场景中有关数据存储的问题。
同任何一门编程语言相比,数据结构确实是晦涩难懂的。举个简单的例子,众多学习数据结构的读者中,可能很多人都能快速学会链表、哈希表、二叉树,还能熟练运用大部分的查找算法和排序算法,但能玩转路径规划、字符串匹配、动态规则等复杂问题的人,却凤毛麟角。
因此,要想学好数据结构,不仅要求学员具备良好的编程基础,还必须具有较强的逻辑分析能力和理解能力,甚至还需要具有一定的空间想象能力,可以这么说,能玩转数据结构的人,其综合实力往往都不差。很多大的互联网公司,更看重的往往不是你精通多少种编程语言,而是综合能力,更确切地说是解决问题的能力。
有些读者可能会问,类似 C++ 可以使用 STL 标准库,Python 代码可以使用 Collections 模块等,很多编程语言都可以使用相应的集成数据结构的框架或者模块,直接拿来用不就可以了吗?
事实上,很多在职程序员在开发过程中,都会套用现有的一些集成数据结构的模块或者框架。要知道,适当的使用是可取的,但不能完全依赖,否则知其然而不知其所以然,即便完成再多的项目,也无非是他人代码的搬运工,个人能力很快会进入瓶颈期,再无提升的空间。
我认为,代码执行性能的好坏无疑能成为众多评判标准中的一个。而想编写出性能高的代码,前提是必须知道如何评判代码的性能,这就不得不使用数据结构中评判代码执行性能的时间复杂性和空间复杂度。
对于某些在职的程序员来说,如果觉得数据结构无用,更多可能是因为你接触的都是一些用户量很少、需要处理的数据量也很少的小项目,实际开发中更注重实现具体的功能,产品的性能要求并非那么苛刻。反之,如果你身处像 BAT 这样的大公司,所开发产品的用户量往往是千万级别甚至亿级别,需要处理的数据量也往往是 TB 甚至 PB 级别,这时产品的性能将是首要考虑的因素,而数据结构和算法的意义将会彻底凸显出来。
总之,和学习某一门编程语言不同,随学即用,常常会带给你学习的快感。有些知识并非学习了就能立竿见影,但学懂它会让你有整体的提升,数据结构就是这样的知识。
声明:当前文章为本站“玩转C语言和数据结构”官方原创,由国家机构和地方版权局所签发的权威证书所保护。
刚刚接触数据结构,初学者肯定有一肚子的疑问,比如:
- 数据结构到底是什么;
- 学数据结构有什么用?
- 数据结构要学习哪些知识;
- 学数据结构要具备什么基础;
- 自学数据结构,怎样学习更高效。
在这篇文章中,我不会深入讲解数据结构中的某个知识点,而是要揭开数据结构的面纱,让大家从整体上对数据结构有一个清晰的认知,致力于帮助读者快速入门数据结构。
1、数据结构到底是什么?
程序员编写的每一个程序,本质上都是对数据进行有效地整合、加工,最终再把处理结果展示给用户。例如,学生信息管理系统是用来管理学生信息的,每一条学生信息都是一个个的数据。程序运行过程中用到的数据,全部位于计算机的内存中。所有数据在内存中的存储状态,比如是集中存放还是分散存放,需要开发者提前做好规划,而这就属于数据结构的研究范畴。
说白了,数据结构是一门研究如何存储数据的学科。
有读者可能会问,存数据还需要研究吗,少量的数据用变量(对象)存储,大量的数据用数组存储,不就行了吗?答案是否定的,接下来通过一个实例展开讲解。
![道路分布图](/uploads/allimg/240819/2-240Q9112Z01W.gif)
图 1 道路分布图
图 1 是一张道路分布图,记录着 V1、V2、V3 和 V4 之间的道路分布,比如 V1 可以直达 V2 和 V3,V3 可以直达 V4,V4 可以直达 V1。图中的每条路都是单行路,比如 V1 可以直达 V2,但 V2 无法到达 V1。
试想一下,如果编写一个道路管理系统,如何将图 1 中的道路信息存储到内存中呢?首先,要想将图 1 存储到内存中,我们需要存储的内容包括:
- 4 个地点:V1、V2、V3 和 V4;
- 道路信息:V1->V2、V1->V3、V3->V4、V4->V1。
将以上两份数据都存储到内存中,就成功的将图 1 存储到了内存里。
如果读者尚未学习数据结构,很可能想不出可行的存储方案。反之如果学过数据结构,这个问题很容易解决,因为数据结构中专门讨论了图 1 这类数据的存储方案,将这类存储方案统称为“图”。
例如,下图是数据结构中的一种存储方案,叫做邻接表,它是图的存储方案之一:
![邻接表存储结构](/uploads/allimg/240819/2-240Q91214204D.gif)
图 2 邻接表存储结构
图 2 中,左侧是一个数组,用于存储 4 个地点;每一行是一个链表,用来存储地点之间的道路信息。如下图所示:
![邻接表存储道路信息](/uploads/allimg/240819/2-240Q912152JW.gif)
图 3 邻接表存储道路信息
数组下标 0 的位置存储的是 V1,后续箭头指向的 2 也是数组下标,由此找到了 V3,说明 V1 能直达 V3;同理,通过后续箭头指向的数组下标 1,说明 V1 能直达 V2。
类似图 3 这种稍复杂的存储方案,除非系统地学习数据结构,否则是不容易想到的。
学习数据结构,就是学习各种数据的存储方案。对于同一份数据,存储方案通常有很多种,选择好的存储方案,后续编码过程中可以更高效地使用内存中的数据,为后续编码提供便利,大幅提高开发效率。
2、数据结构要学习哪些知识?
数据结构里囊括了各种数据的存储方案,并将它们进行了分门别类,分别是线性表、栈和队列、串、数组和广义表、树、图、查找表。这里给读者分享一张我精心整理的思维导图,图中罗列了数据结构几乎所有的知识点(猛击这里查看超清大图):
![数据结构思维导图](/uploads/allimg/240819/2-240Q9123605Z7.gif)
图 4 数据结构思维导图
3、学数据结构要具备什么基础?
学数据结构需要什么基础,这是很多初学者关心的。这里我明确的告诉大家,学习数据结构需要你熟练掌握一门编程语言,仅此而已。数学、英语基础不好,也能学习数据结构。注意,我说的是熟练掌握一门编程语言。以 C 语言为例,所谓数量掌握,最简单的衡量标准是能够独立编写一下小项目,比如学生信息管理系统、贪吃蛇游戏、推箱子游戏等。
很多读者觉得数据结构难,实际上因为编程基础薄弱导致的。举个简单的例子,有些初学者能够理解数据结构中存储数据的思想,但就是不会编码实现,这就是典型的编程基础薄弱,编程语言掌握地不熟练。
4、自学数据结构,怎样学习更高效?
学习数据结构,建议读者找一套文字教程和一套视频教程:- 文字教程: 市面上有很多数据结构教材,水平参差不齐,有些教材通俗易懂、深入浅出,而有些喜欢玩弄概念,总是把简单的问题复杂化,语言表达含糊不清,总之就是不说人话。
- 视频教程:尤其是自学数据结构的读者,视频教程几乎是必备的学习资料。数据结构中确实包含一些复杂的存储结构(比如树、图),借助视频教程中的动画演示,可以很直观地看到数据的存储状态。
和视频教程相比,文字教程有一个与生俱来的优势,就是能快速回顾之前所学的知识。学习数据结构,你会接触到很多存储数据的新思路,如果不经常回顾,很容易会遗忘。文字教程和视频教程相互搭配,学习数据结构会事半功倍。
此外学习数据结构的过程中,做以下两件事可以提高自己的学习质量:
- 多动手敲代码,敲得越多,数据结构掌握得就越牢固;
- 必要的时候,可以用笔将数据的存储结构画出来。
手绘数据的存储状态,对学习数据结构非常有帮助。举一个简单的例子,如果我们想象不到链表是怎样存储数据的,可以尝试动手画一个链表,如图 1 所示:
![链表](/uploads/allimg/240819/2-240Q912495W55.gif)
图 5 链表
在这张图中,链表的头指针、各个结点的存储状态都一目了然。通过画图,可以加深我们对各个存储结构的认知,对编写程序实现各个存储结构有莫大的帮助。
5、学数据结构有什么用?
通过前面的讲解大家知道,数据结构并不是一门具体的编程语言,它教会我们的是一种思维方式,即如何以更优的方式存储数据。或者正是由于这个原因,很多读者感觉数据结构虚无缥缈,无法触及,不如学习 Python、Java 等这些编程语言可以随学随用、掷地有声,久而久之觉得学习数据结构没用。那么,数据结构真的无用吗?当然不是。作为计算机专业最重要的必修学科之一,计算机专业考研的必考知识,以及众多 IT 公司笔、面试的侧重考点,仅仅这些光环,就足以说明学习数据结构的重要性。
毋庸置疑,数据结构不仅有用,更应该是每个程序员必须掌握的基本功。
1) 提升程序员的逻辑思维
首先,通过学习数据结构,可以大大拓宽我们的思维模式。掌握了数据结构与算法,我们看待问题的深度、解决问题的角度会大有不同,对于个人逻辑思维的提升,也是质的飞跃。具体来讲,对于同一个问题,数据结构往往会教给我们不只一种解决思路。举个例子,假设我们需要从众多数据中查找出符合要求的元素,多数人就只能借助数组这种简单的存储结构来实现,而通过学习数据结构我们会知道,解决此类问题既可以通过构建二叉排序树、平衡二叉树、甚至红黑树、B+/B- 树来解决,还可以借助哈希表解决。
再举一个例子,几乎所有的编程语言中都提供有数组这种存储结构,但如果没学过数据结构,就绝不会想到,数组还能以链表的形式使用(也就是静态链表,后续章节会做详细讲解)。
事实上,数据结构也有众多编程语言无法比肩的优势。无论是 Java、Python、C++、PHP 还是其他编程语言,无时无刻不在更新迭代,而数据结构却永远不会过时,其包含的存储数据的思想,已经近乎将所有可能的情况都囊括其中,能解决 99% 的实际场景中有关数据存储的问题。
2) 能力高低的分水岭
有很多读者(其中不乏在职的程序员)都会问一个问题,即为什么很多 IT 公司都特别注重对数据结构的考察?读者大可以这样认为:数据结构是众多 IT 公司评判面试人员能力高低的重要工具。同任何一门编程语言相比,数据结构确实是晦涩难懂的。举个简单的例子,众多学习数据结构的读者中,可能很多人都能快速学会链表、哈希表、二叉树,还能熟练运用大部分的查找算法和排序算法,但能玩转路径规划、字符串匹配、动态规则等复杂问题的人,却凤毛麟角。
因此,要想学好数据结构,不仅要求学员具备良好的编程基础,还必须具有较强的逻辑分析能力和理解能力,甚至还需要具有一定的空间想象能力,可以这么说,能玩转数据结构的人,其综合实力往往都不差。很多大的互联网公司,更看重的往往不是你精通多少种编程语言,而是综合能力,更确切地说是解决问题的能力。
有些读者可能会问,类似 C++ 可以使用 STL 标准库,Python 代码可以使用 Collections 模块等,很多编程语言都可以使用相应的集成数据结构的框架或者模块,直接拿来用不就可以了吗?
事实上,很多在职程序员在开发过程中,都会套用现有的一些集成数据结构的模块或者框架。要知道,适当的使用是可取的,但不能完全依赖,否则知其然而不知其所以然,即便完成再多的项目,也无非是他人代码的搬运工,个人能力很快会进入瓶颈期,再无提升的空间。
3) 程序性能好坏的评判标准
对于如何评判一个人编程能力的强弱,不同的人有不同的标准,或许是看中他编写代码的可读性,扩展性、是否健壮等等。我认为,代码执行性能的好坏无疑能成为众多评判标准中的一个。而想编写出性能高的代码,前提是必须知道如何评判代码的性能,这就不得不使用数据结构中评判代码执行性能的时间复杂性和空间复杂度。
对于某些在职的程序员来说,如果觉得数据结构无用,更多可能是因为你接触的都是一些用户量很少、需要处理的数据量也很少的小项目,实际开发中更注重实现具体的功能,产品的性能要求并非那么苛刻。反之,如果你身处像 BAT 这样的大公司,所开发产品的用户量往往是千万级别甚至亿级别,需要处理的数据量也往往是 TB 甚至 PB 级别,这时产品的性能将是首要考虑的因素,而数据结构和算法的意义将会彻底凸显出来。
别忘了,数据结构也是很多大 IT 公司选拔人才的重要标准。
总之,和学习某一门编程语言不同,随学即用,常常会带给你学习的快感。有些知识并非学习了就能立竿见影,但学懂它会让你有整体的提升,数据结构就是这样的知识。
声明:当前文章为本站“玩转C语言和数据结构”官方原创,由国家机构和地方版权局所签发的权威证书所保护。