严蔚敏数据结构查找的基本操作_数据结构与算法之绪论(二)

    我们继续来学习数据结构与算法,前面我们大概讲了一下数据结构是什么,有了一个大概的认知。

    常用数据结构

    现在我们来介绍一下我们在接下来的学习中要学习的数据结构:

03b1424701c9756977ce57e662e7bf62.png

    当然,这里面又可以分成若干个小点,比如线性表又可以分成数组和链表;树可以分成二叉树、一般树;图又可以分成有向图和无向图;听起来好像很多很难,但是只要你们认真看认真学是肯定能够学会的(学不会私聊我亲自教你)。

   逻辑结构和物理结构是什么?

    这里又要介绍两个概念:逻辑结构和物理结构,他们是描述数据结构的两个方面

    先看看啰嗦的数学概念吧:

6875f797c5a02b4e5b7d60650d6e08ed.png

    举个简单的栗子:

定义一个复数的数据结构Complex=(C,R)其中C={C1,C2}      //C是两个实数的集合R={}    //这个表示C1在前,是该复数的实部;C2在后,是该复数的虚部

    像这种定义了先后顺序的关系就叫做逻辑结构,要注意的是逻辑结构是相对于数据元素而言,我上面举的例子中C1、C2都是数据元素。

    至于物理结构,其实就是字面意思,就是物理块是怎么组织的。

    其实用数组和链表可以很好地解释逻辑结构和物理结构:

    数组的逻辑结构是顺序的、物理结构也是顺序的(这就是它可以使用下标快速定位某个数据元素的原因);

    链表在逻辑上是连续的但是在物理上却不是连续的(因为链表的结点是通过指针来找到下一块结点的,所以它查找元素比数组要慢得多)

    关系的映像方法

    既然讲到数组和链表,那就顺带提一下两种映像方法:

c7cf693f9a2ab71f97cc044e367308b2.png

代表人物---数组

2b8b0950d45b20476d9a2f01a637fd88.png

代表人物---链表

    数据类型

    数据类型学过C++或者其他语言的同学肯定都接触过,无非就是Char(字符)变量、Int(整形)变量、Double(双精度浮点数)变量等等,这里就不再多叙述了。

8d03185fb81bf7ad6126eb028331dc4b.png

抽象数据类型(Abstract Data Type)

    抽象数据类型也叫ADT,它是用来描述一个数学模型以及定义在该模型的一组操作,其实它跟伪代码差不多,我们可以用(D,S,P)三元组来表示一个抽象数据类型(ADT),具体是这样的:(建议先看看下面的栗子)

用(D,S,P)三元组表示其中, D 是数据对象,      S 是 D 上的关系集,      P 是 D 上的基本操作集。               再具体一点: ADT 抽象数据类型名 {   数据对象:〈数据对象的定义〉   数据关系:〈数据关系的定义〉   基本操作:〈基本操作的定义〉} ADT 抽象数据类型名其中基本操作的定义格式为:基本操作名(参数表)    初始条件:〈初始条件描述〉    操作结果:〈操作结果描述〉 参数表可以出现的参数:赋值参数:只为操作提供输入值。引用参数:以&打头,除可提供输入值外,还将返回操作结果(和C++的引用差不多)。初始条件:描述操作执行之前数据结构和参数应满足的条件,若不满足,则操作失败,并且返回相应的出错信息。操作结果:说明操作正常完成之后,数据结构的变化状况和应返回的结果。若初始条件为空,则省略之。

    这玩意在数据结构的书上到处都是,考试的时候也会要求写出来,所以务必要掌握。

    看了定义可能会觉得有点懵,下面举个具体栗子:

6b91700df787821cfe9573f7e77bc97b.png

254e2e9ed646fa48d725074e65f8477e.png

1b54a96217eec8d0fc505515d74cdba1.png

算法    

    这里再提一下算法这个概念,值得一提的是当我看完整本数据结构的时候,我发现算法与结构是并存的、息息相关的,也就是说不同的数据结构有不同的算法。

    比如对于数组的遍历算法用到的是下标的增长,而链表的遍历算法则是指针的不断变换。

74b702fb3f3ce531544caff7a1171d0a.png

   (数组与链表,图来源于网络)

算法的要求(这个有时会出填空题噢)

    这小节都是概念性的东西,背一下就好了

(一)算法一定要满足的五个重要的特性:1.有穷性    2.确定性    3.可行性4.有输入    5.有输出1、有穷性,就是你写的算法要能在有限时间内输出结果2、确定性,就是对于相同的输入输出必定相同3、可行性,算法中的所有操作都必须足够基本,即都可以通过已经实现的基本运算执行有限次来实现。4、有输入,作为算法加工的数据对象,通常体现为算法中的一组变量。有些变量需要在算法执行过程中输入,而有的算法表面上可以没有输入,实际上已被嵌入到算法之中。5、有输出,这个不用说了,没输出的话我不知道你写这个算法是图啥(二)算法设计的目标正确性、可读性、健壮性、高效率与低存储量需求

如何评估算法的好坏

    一个算法的好坏取决于时间与空间这两个维度

    一般有两种评估方法

    一种是事后统计法,就是你先跑一下这个程序,拿计时器计时,然后打开你的任务管理器看看你的程序占多少内存。

    另一种是事前统计法,我带着大家算一下下面这个栗子就知道了

for(int i=0;i//这里也要执行n+1次,为什么是n+1而不是n呢?  for(int j=0;j//这里要执行n(n+1)次,为什么不是(n+1)²呢  }}所以这个程序总共要执行 n+1+n(n+1)次,所以这个程序的时间复杂度是O(n²)问题1:为什么第一层的循环是执行n+1次而不是n次?答:这里我假设n=1,首先j=0的时候会判断一下是否J<1,这里就算一次,然后J自增1,然后继续判断,这里又算一次,此时j不小于1跳出循环,所以总共是2次,即n+1次。也就是算判断的语句也要算进去。但实际上不用算这么清楚,因为时间复杂度只算到最高次就可以了。问题2:为什么第二层的循环是n(n+1)而不是(n+1)²?答:很明显,他的上层循环除去判断操作只会执行n次,所以是n(n+1)问题2:为什么时间复杂度是O(n²)而不是O(n+1+n(n+1))²答:只算最高次,其他低次幂的都被省略了。

    至于空间复杂度怎么计算,无非和上面差不多,只不过换成了数用了多少个变量罢了

    常见的时间复杂度

76e78e5e73adba2ef0d914059e3017d8.png

     在这里引入一个术语:问题规模,通俗地讲就是上面例子中的n,问题规模一般与输入数据量成正比。比如你要遍历一个链表里的所有数,这个链表里有5个结点那么n=5,如果有50个结点那么n=50。当然我们不会写成O(5)或者O(50),而是写成O(n),这样才具有一般性。

    要注意的是,O(1)的意思并不是只执行了一次,而是执行了常数次,这个常数是确定的、不随着n的变化而变化,比如数组的查找就是O(1)时间复杂度的,因为只需进行下标的计算然后根据下标找到目标元素即可。

    绪论的内容大概是这么多,下一章我们将学习线性表。觉得有用的别忘记转发还有点个在看和赞噢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值