python web为什么要学数据结构与算法面试官为什么总问那几个算法和线性表二叉树
算法是什么?
举个简单的例子
当年刘景生病危刘琦被卷入继位之事 无奈求助于诸葛亮
以上古兵书为由 邀孔明阁楼相谈….
诸葛亮曾说 那部阵书开篇就是阵法源自于心法
所以古代军师进步也是看兵法
算法也是同理 虽然我们作为web后端开发人员
但是每天所见所闻日子久也就适应了。
但是想要再进一步 两种方法
一 多看高质量代码
二 看算法
我们作为web开发可能算法运用的不是很多
每天也就是写接口调接口和产品经理撕
但是算法最重要的地方是会帮你扩充你的逻辑思维
可能刚看算法的人认为太难了我真学不来
举个例子 现在正是dota2ti大赛 (作为一个资深的dota玩家我也是有关注的)
让你天天打ti还会觉得难吗?入门就好了
说说面试官的问题
之前我也有跟老大去面试新人
1 线性表是什么
线性表是一个数据结构的统称
大致分为两种 一种是序列表(就是python的列表)
优点是查询是时候可以一次性定位 因为所有元素地址是相连的(数据内置)
数据外置所指是存储类型不一样 所以表内内存地址也不同 各有各的地址 所以在在列表存储数据时推荐大家只存储一种数据类型
缺点 对于顺序表来说他的内存空间是整体的 一旦发生改变它整个存储空间都会发生改变(扩充数据序列表)所以说所需整体空间是很大的
固定扩充 稳定但是慢
倍数扩充 比如列表 它在扩充是每次会扩充五倍的存储空间 当元素达到5W时改为1倍
使用顺序表(列表)时候 尽量不要使用+= 使用往尾部添加 如果头部insert添加会比append慢30倍(我试过insert和append)
原因就是你往序列表添加时候如果是头部下标为0那就意味着 整体列表 后移一位下标
第二种就是链表
链表大体分为两部分部分 1元素区2指针区 (两种一种是上个元素指针区一种是下一个元素的指针区) 所有数据都是链接在一起的所以叫链表
优点是可以利用内存中零碎的空间进行存储但是你利用零碎的空间
缺点当你利用零碎的空间时开销也是巨大的而且你在取数据时候也做不到O(1)因为表里的空间都是互不相连的
线性表一般(在python)用的比较少,如果有幸用到 添加数据时 要避免尾部添加 因为他添加时候是循环到最后一指针指向到头部时候会把最后一个的指针
指向新元素将新元素指针指向头部元素
头部添加反而是O(1) 只需要将新元素指向头部元素 即可
最后一点树的基础就是线性表组成的之后 树会在后面详谈
栈和队列是什么?
通俗比喻栈就是一个杯子 后进先出 队列就是先进先出
栈和队列的实现也是用线性表实现的
用序列表(列表)实现简单
但是需要考虑时间复杂度你别用序列表一直头部添加&链表一直尾部添加 这样就得不偿失了
说说冒泡排序
冒泡排序是最基础的算法排序
思想是两层循环外循环控制整体循环次数 内循环第一次循环将最大值 第二次循环将倒数第二大的值找出依次类推
快速排序呢(快排)
快排顾名思义排序很快
思想 分为两层
一层是找两个游标 一个mid_value(中间值) 一个游标从下标0开始 一个下标从len-1尾部开始
先让右侧游标移动 碰到比mid大的游标值-1 碰到比mid小的将值赋值给 左侧游标
左侧游标开始移动 比mid小的 下标+1 比mid大的赋值给 右侧游标 然后右侧游标 继续执行
当 左侧游标和右侧游标相遇 mid的下标也就出现
自此 mid左侧 全是比他小的右侧全是比他大的
然后是重要的第二层递归
递归调用自己去执行比自己小的左侧
递归调用自己去执行比自己大的右侧
有个坑点 操作的是同一个列表所以别用切片
切片是返回新列表! 内存引用变了!
注意控制递归值!
试想如果你有10W个数据 他会递归出来多少个自己
也就是说函数的运行大小的同时也决定了耗费多少性能
典型的用性能换效率
你还知道哪些排序?
选择排序插入排序希尔排序归并排序
选择排序插入排序和冒泡差不多就不细说了
但是有一个排序比较特殊 是根据插入排序的二次改进
那就要说插入排序了 插入排序是有两个下标0和1依次比 如果1比0大就互相交换位置 依次类推 5会跟43210比
希尔排序 刚才也说是根据插入排序的二次开发
多了一个中间值 循环时候从取决于gep的值
列入列表长度是8 我取整除2 那就是4
就从4开始循环表里 每次下标4+1+1+1
就多了一层gep而已 但是综合考虑时间复杂度是O(n^2)但是据说用数学精准计算可以达到 n^1.3
归并排序其实也是递归 只是一直分分分 然后最小的与之交换顺序 但是用的是切片 最后返回同一个列表
下面就到树了。 问到最多的就是二叉树
树的应用场景是什么?
蛮多的
比如 前端的html 里面包含 div 啊 a啊 li啊 各种标签
数据库索引也是
文件的目录
路由协议的算法
很多ai算法都是树的搜索 机器学习的decisiontree也是树结构 等等不举例了….
二叉树分为两种一种是有序二叉树和无序二叉树 无序的没有意义我们就说有序二叉树
二叉树也有完整二叉树之分完整的 除了底层之之外其他的度都是2 一般的最好理解 每个节点最多有两个度
当说到快排的 递归时候是不是一直在分为两个自己 不管左侧的还是又侧的 一直分一直分就是一个二叉树 个人觉得这个解释是很合适 虽然没有依据
但确实就是二叉树的特征
树的存储也分两种表 一种是顺序表一种是链表
顺序表存固然是好 查询方便嘛。。 但是空间太大不采用
用链表存储 因为链表可以利用琐碎的内存空间 在细一点说用队列
二叉树的遍历
分为 层级遍历 最好理解 的就是 每次遍历的值是123456789
先序遍历 依次遍历根左右 中序遍历 左跟又 后序遍历 左右跟
用递归不算难
当然有些面试官还会问你
画树会吗
画树 需要两种序列其中中序是必不可少的
我们就拿简单的123456789来说
先序遍历是 0137849256
中序 781940526
后序 7839412560
假如给 先序和中序
先序 0137849256 中序 781940526
为什么一定要中序 因为中序能将左右分开
中序 78194 0 526 0 137849 256
左侧与右侧出来了 先序的也就出来了。 在回想 先序的规则是 根左右 中序的规则是 左跟右
有此依据再大的树只要足够的时间人为画也能画出
中序和后序也是一样 可以找出
好再说说为什么面试官要问 线性表 栈 冒泡 快排 二叉树 吧
作为一个web开发 他不会问你特别深 因为你又不是做 算法工程师 他的想法只是想看看你平时爱不爱学习 逻辑思维怎么样
先说线性表 你答的出来说明你知道数据是如何存储的 栈 只是高一级而已 看看你是否知道栈 如果你把队列和双端队列都说出来他会更高兴
冒泡和快排 为什么那么多排序只问快排和冒泡?
冒泡是算法的基础 只有你知道冒泡他才会往后继续追着问 我个人感觉冒泡都不算法 就是两层循环而已
冒泡他很稳定,但是很慢很慢 你想想你如果有千万数据 那一次 遍历 从头到尾不敢想了。。
快排 快排是接触到递归了。 他问你的同时如果你能把递归也说的非常好 那说明你对递归也有了解 况且快排真的很快!!! 数据越大 递归深度越深
典型的用性能还效率 虽然不算稳定 一般也没有一个列表里放数据的同时也放了元组把。。好如果非要放!! 那就用归并排序呗。
如果他是否知道其他算法
冒泡插入选择 shell 一个套路 快排和归并也是一个套路
所以他只问冒泡和快排
忘记写二分法了。。
那个也是用递归一直分分分直到找到为止。。 就跟着你查字典一个样 比如你查猿 先把字典分到一半 y如果在前半部分 在分 直到分到为止
一般树不会问的特别深 最多就是遍历了吧
层级遍历 先序 中序后续 答出来就好了。 如果让你花树 那就 跟他要张纸 把最简单那个逻辑123456789 给他虑一遍完事!
但是web开发一般不会太深, 多思考一下技术点为重 不知道的就说不知道 没什么丢人的。
说的比较笼统 大概就是这个意思 最近我准备把大学的算法导论和算法4拿出来 在仔细琢磨一遍 好好学学思想