数据结构和算法在我们日常开发业务代码时,使用到的场景并不多。很多程序员职业生涯可能从来都没有涉及过,但是这却是很多面试都必考的环节,所以这成为了很多程序员心中的痛点问题。
一、为何要学习数据结构和算法
数据结构和算法虽然用到的场景并不多,但它却是程序员基础能力很重要的体现。自己当初学习的原因有如下几点:
- 面试需要,尤其是大厂面试,都喜欢考察算法,让人现场写代码。
- 想要挑战自己,成为更专业的人员。很多底层的框架不需要自己实现,并不代表什么都不需要了解。
- 对编程还有追求,不想被行业淘汰。这其中性能好坏就是其中一个非常重要的评判标准。
二、算法效率的评估标准
算法执行的效率主要通过复杂度的分析来评估。这其中就包括时间复杂度和空间复杂度,现在计算机内存也不值钱配置的容量越来越高,空间复杂度其实并不是什么大的问题,下面主要分析下算法的时间复杂度。
算法时间复杂度的计算方式一般使用大O时间复杂度表示法,它并不具体表示代码真正的执行时间,而是表示代码执行时间随数据规模增长的变化趋势,也叫做渐进时间复杂度。
常见的时间复杂度包含如下(按数量级递增):
三、常见的数据结构和算法
对于计算机来说存储在内存中的数据要么连续,要么非连续,其实也就只存在数组和链表两种存储结构。其它所有的数据结构都是逻辑上的概念,建立在数组和链表的基础之上。
3.1 数组
一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据。
线性表:表示数据排成像一条线一样的结构。每个线性表上的数据最多只有前和后两个方向。数组、链表、队列、栈等也都是线性表结构。
非线性表:数据并不是简单的前后关系。如二叉树、堆、图等
数组在内存中属于一个连续存储区域,查找的效率是比较高的。但是插入和删除都会影响后续的连续数据,所以时间复杂度都是O(n)
3.2 链表
链表,并不需要一块连续的内存空间,通过“指针”将一组零散的内存块串联起来使用。
单链表
双向链表
循环链表
| 时间复杂度 | 数组 | 链表 |
|---|---|---|
| 插入、删除 | O(n) | O(1) |
| 随机访问 | O(1) | O(n) |
其它数据结构都是在数组和链表的其中进行包装,而衍生出来的逻辑概念,如散列表
散列表:用的是数组支持按照下表随机访问数据的特性,所以散列表其实就是数组的一种扩展,由数组演化而来。如果没有数组,就没有散列表。
3.3 数组结构和算法列表
数据结构:数组、链表、栈、队列、跳表、散列表、二叉树、红黑树、递归数、堆、图、Trie树等等
算法:递归、排序、二分查找、哈希算法、深度优先搜索、广度优先搜索、BM算法、贪心算法、分治算法、回溯算法、动态规划算法等等
四、数据结构和算法使用场景
4.1 浏览器前进后退的功能
- 使用两个栈X和Y
- 首次浏览的页面依次push->栈X
- 点击后退时,依次从栈X -> pop, push -> 栈Y
- 点击前进时,依次从栈Y -> pop, push -> 栈X
- 栈X无数据,说明不能继续后退
- 栈Y无数据,说明不能继续前进
4.2 如何根据年龄给100万用户排序
- 假设年龄的范围最小1岁、最大不超过120岁
- 可以遍历100万用户,根据年龄将其划分到120个桶里
- 依次顺序遍历这120个桶中的元素
- 这样就得到了按照年龄排序的100万用户数据
4.3 Word文档中单词拼写检查功能如何实现
- 常用英文单词大概20万左右,平均长度是10个字母,20万英文单词大约占2MB存储空间
- 可以使用散列表存储整个英文单词词典
- 当用户输入某个英文单词时,能够在O(1)时间复杂度就查找到单词。
需要结合数据结构和算法的场景是非常之多的,上面仅仅举了几个简单的示例,表示我们日常工作和生活中其实都是会遇到,只是我们可能未注意。
五、小结
数据结构和算法、与操作系统,计算机网格一样,都是比较偏底层的知识。你基本上也没有速成的办法,需要你沉下心来不停的思考和练习,才有可能融汇贯通成为你掌握的智慧。
生活前进的动力来源于你还有求知的欲望、好奇的冲动,你认为人生还有各种可能,而不是一尘不变。