数据结构与算法笔记:Big-O记号, 数据结构与算法的关系以及几种基本的数据结构

本文深入探讨算法评估标准Big-O记号,解析算法与数据结构的内在联系,介绍Array、Vector、List、Stack、Queue、Tree及Graph等基础数据结构的特点与应用,揭示算法设计策略与资源消耗之间的微妙平衡。

关于算法

  • 算法其实有无数种,就市面上的算法而言,普通人可能知道的算法不到千百分之一,但是我们却可以一定程度上驾驭算法,是因为我们知道算法设计的策略
  • 我们在解决问题的时候,头脑中想到的都是策略,这些算法可以串成一串,每一串可能都是基于一种策略设计出来的

Big-O 记号

  • 我们研究算法,需要懂得如何判断算法的优劣,越好的算法消耗的资源就越少
  • 计算的资源有两点:一个是时间,另一个空间,我们最主要关注的其实还是时间

在这里插入图片描述

  • 同一个算法在解决某一个问题的时候,针对不同的n(问题的规模), 它所需要的时间成本running time, 画成一条曲线T(n)
  • T(n)这个函数就是当我们给定了一个规模为n的特例之后,用这个算法在某一个特定n所需要消耗的时间成本,一般来说,是一条这样的曲线。
  • 在实际情况中,并不能精确得到这条曲线,其实也没有必要得到这条曲线,我们只要知其大略即可,即粗略的估计
  • T(n) = O(f(n))
    • 用一个f(n)去粗略的估计T(n), 如果这个估计可行的话,再在其前面加个O,这样来表示。
    • 可以估计的条件:∃ c>0  s.t.  T(n)<c⋅f(n)   ∀n>>2\exists \ c > 0 \ \ s.t. \ \ T(n) < c·f(n) \ \ \ \forall n >> 2 c>0  s.t.  T(n)<cf(n)   n>>2
      • 取一个c,当问题规模足够大的时候(这里∀n>>2\forall n >> 2n>>2表示足够大),使得 T(n)<c⋅f(n)T(n) < c·f(n)T(n)<cf(n)
      • 也就是这时候的c⋅f(n)c·f(n)cf(n) 可以估计T(n), 这个f(n)的曲线如上图虚线表示
      • 这样估计的好处是:常系数,低次项从此可忽略,即:O(f(n))=O(c⋅f(n))  ;  O(na+nb)=O(na),a≥b>0O(f(n)) = O(c·f(n)) \ \ ; \ \ O(n^a + n^b) = O(n^a), a \geq b > 0O(f(n))=O(cf(n))  ;  O(na+nb)=O(na),ab>0
      • 举个例子:Ex:5n⋅[3n⋅(n+2)+4]+6<5n⋅[6n2+4]+6<35n3+6<6⋅n1.5=O(n1.5)E_x : \sqrt{5n·[3n·(n + 2) + 4] + 6} < \sqrt{5n·[6n^2 + 4] + 6} < \sqrt{35n^3 + 6} < 6·n^{1.5} = O(n^{1.5})Ex:5n[3n(n+2)+4]+6<5n[6n2+4]+6<35n3+6<6n1.5=O(n1.5)

算法和数据结构的关系

  • 算法和数据结构是一个硬币的两面, 好的算法在研究透了以后会慢慢积淀为数据结构
  • 高级算法的支撑都来自于数据结构

几种基本的数据结构

1 ) Array & Vector

在这里插入图片描述

  • 最基本的线性结构是Array,一个线性的序列
  • n个元素排成一行,下标从0开始,到n-1结束,如果要用n表示,请注意左闭右开
  • 表示方法:A[n]、A[0, n-1]、A[0, n)
  • Array后来被封装起来变成了Vector,对外提供快速操作的接口
  • Array和Vector都可以以常数O(1)的时间找到某一下标k对应的元素A[k]
  • 但是移动元素(删除、插入)很麻烦,需要一个个的操作

3 ) List & Linked List

在这里插入图片描述

  • 和Vector对应的另一种线性结构List, 由一组元素构成,它们之间排成队
  • 在List的内部,拿第k号元素来说,有它的后继和前驱元素, 它们之间都是以一个切实的称之为link(succ,pred)的东西来彼此指引
  • 在Array和Vector中是以call by rank的方式来操作元素,在List中是以call by position的方式来操作
  • List的好处是拆掉某一元素只要重新拼接断点处即可,所以这种数据结构操作元素(添加,删除)很简单
  • List在查找的时候,比如从某一端0顺藤摸瓜找到1,继而找到其他, 所以查找操作很慢,和Vector正好互补

3 ) Stack

在这里插入图片描述

  • 栈也是一个线性的次序,像是堆椅子一样, 后进先出,LIFO
  • 添加元素push只能加到开放的一端,也就是栈顶
  • 栈顶元素叫做top
  • 弹出元素pop也是从栈顶弹出
  • 算法的精妙都蕴含在这些push,pop的组合之中

6 ) Queue

在这里插入图片描述

  • 和栈并列的一种数据结构叫做Queue队列,是个线性结构,先进先出 FIFO
  • 进队操作叫做 enqueue, 出队操作叫做 dequeue, 分别由两端各司其职
  • 队列入口的地方叫做rear后端, 出口叫做front前端
  • 从后端 enqueue,从前端 dequeue
  • 这是一种效率最高最公平的资源分配机制
  • 在计算机中,CPU的时间在不同进程中享用,多个进程并发使用CPU
  • CPU会把所有占用资源的进程组织成一个queue, 以这种方式来轮值服务,从而达到一种整体公平和高效

7 ) (Binary) Tree

在这里插入图片描述

  • 树是一种半线性模型(分叉有方向),树就像是一个家族一样慢慢繁衍,分支越来越多,形成代际关系,是一种无环的结构
  • 树结构举例:互联网域名,计算机目录等,一层套一层其实是比较头疼的,主要是不规范,难以管理,如上图的第三颗树
  • 进而衍生了上图的第二颗树, 每个父节点只需要管理它自己的’长子’ 由’长子’管理’次子’,以及’长子’的孩子, 依次有章法的管理下去
  • 对于第二棵树的优势是:只需要记住谁是自己的’弟弟’,谁是自己的’长子’即可。
  • 注:这里不考虑性别,只按男性称为来表示,当然也可以用女性称谓。
  • 继而优化变形,八字排开,变成了第一棵树,对于A节点来说, 长子D和弟弟B并列排开,变成了二叉树结构
  • 这时候每个节点不再有任意节点了,而最多只有两个孩子
  • 我们很多时候研究树的结构都是倾向于二叉树结构,有时候也会有多叉树结构

8 ) Graph as Matrix

在这里插入图片描述

  • 图是一种较为复杂的数据结构,如微信里的好友关系,对等和不对等
  • 第一个图是无向图,第二个是有向图,第三个是网络图
  • 分别可用下面矩阵形式表示
    • 无向图对称型, 有冗余,真正有效的只有一半
    • 有向图, 不对称, 不浪费
    • 网络图,有关系,也有权重,可对称,可不对称,来源于数学
  • 网络图占用资源非常巨大,有很多没有用的东西,需要进一步优化, 下面来谈谈

9 ) Graph as Vector < List >

在这里插入图片描述

  • 通过Vector<list>来表示Graph, 也就是 Graph as Vector<list>
  • 竖向用一个Vector表示,Vector的每一行都是一个个的List
  • 只记录有效的部分,无效部分略过,节省了很多空间
  • 但是在查找效率上有一定的低效,需要找到Vector的入口,期望在相应的List中找到目标元素
  • 其实数据结构和算法没有万能的,没有万能的算法解决所有问题
  • 我们学的其实是一种折中的方法,找到一个解决问题的平衡策略
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值