数据结构与算法基础

基本概念

计算机科学的研究对象是问题、解决问题的过程,以及通过该过程得到解决方案。算法是具有有限步骤的过程,依照这个过程能解决问题。因此,算法就是解决方案

计算机科学是研究问题及其解决方案,以及研究目前无解的问题的科学。可以简答的认为计算机科学就是研究算法的科学。

  • 可计算:若存在能够解决某个问题的算法,那么该问题是可计算的。

  • 编程:通过编程语言将算法编码以使其能被计算机执行的过程。

  • 数据:人们利用文字符号、数字符号以及其它规定的符号对现实世界的十五及其活动所作的抽象描述。

    例如,我们描述当前的温度位 18 摄氏度。

  • 数据元素和数据项:表示一个事物的一组数据称作一个数据元素;构成数据元素的数据称为该数据元素的数据项。

    例如,我们描述的学生的信息可以是一个数据元素,它的数据项包括姓名、年龄、性别、学号等即为构成数据元素的数据项。

  • 数据类型:一组值和一组这些值的操作的集合,数据类型能够帮助我们解读二进制数据的含义,内建的底层数据类型(又称原生数据类型)提供了算法开发的基本单元。

  • 抽象:计算机科学也研究抽象,抽象思维使得我们能分别从逻辑视角和物理视角来看待问题及其解决方案。

    例如,一辆汽车对于驾驶员来说一般只需要关注启动、换挡、刹车,以及操作方向盘,从抽象角度来看,就是从逻辑视角看待这辆车,驾驶员只是使用了汽车设计者提供的功能(接口)来完成将自己从一个地方运送到另一个地方。但对于汽车设计或者修理工来说,更需要关注汽车工作和实现的细节,这就是物理视角。

    • 过程抽象:过程抽象将功能的实现细节隐藏起来;过程抽象的结果体现为函数
    • 数据抽象:对数据类型的定义和使用过程,数据抽象的结果体现为数据类型。
  • 抽象数据元素:没有实际含义的数据元素,例如 a0 a1、a2 … an-1

  • 抽象数据类型(Abstract Data Type,ADT):一个逻辑概念上的类型和这个类型上的操作集合。对使用者隐藏数据表示的数据类型,从逻辑上描述了如何看待数据及其对应运算而无需考虑具体实现。通过数据抽象,我们对数据进行了一层封装,其基本意思是封装具体的实现细节,使它们对用户不可见,者被称为信息隐藏

  • 数据结构:抽象数据类型的实现。

  • 数据的逻辑结构:数据元素直接的相互联系,一般分为线性结构、树型结构和图型结构三种,其中树型结构和图型结构又可合成为非线性结构。

    • 线性结构:除第一个和最后一个数据元素外,每个数据元素只有唯一的前驱数据和唯一的后继数据元素。
    • 树型结构:除根节点外,每个数据元素只有唯一的前驱数据元素,可有零个或若干个后继数据元素。
    • 图型结构:每个数据元素可有零个或若干个前驱元素和零个或若干个后继数据元素。
  • 数据的存储结构:数据元素在计算机中的存储方式。数据存储结构的基本形式有两种:顺序存储结构和链式存储结构。

    • 顺序存储结构:把数据元素存储在一块连续的地址空间的内存中,其特点是,逻辑相邻的元素在物理上也相邻,数据间的逻辑关系表现在数据元素的存储位置关系上。
    • 链式存储结构:用一组任意的存储单元存储线性表的数据元素(这组存储单元可以是连续的,也可以是不连续的),其特定是,逻辑上相邻的数据元素在物理上(即内存存储位置上)不一定相邻,数据间的逻辑关系表现在节点的链接关系上。
  • 数据的操作和数据的操作集合:一种数据类型数据允许进行的某种操作称作数据的操作,如插入数据元素、删除数据元素等;一种数据类型数据所有的操作称作数据的操作集合。

  • 算法:描述求解问题方法的操作步骤集合。算法的描述语言有三种形式:文字形式、伪代码形式和程序设计语言形式。

算法的性质和设计目标

任何算法设计都满足以下性质:

  • 输入性:具有零个或多个输入。
  • 输出性:一个或多个输出或操作。
  • 有限性:执行语句序列有限。
  • 确定性:每条语句含义明确,无二义性。
  • 可执行性:每一条语句都应该在有限的时间内完成。

算法的设计应满足以下目标:

  • 正确性。
  • 可读性。易于理解。
  • 健壮性。输入非法数据时,算法能做出适当的处理,而不应该产生不可预料的结果。
  • 高时间效率。算法时间效率是指运行算法需要花费时间的多少。
  • 高空间效率。算法的空间效率是指运行算法需要占用的额外内存空间的多少。

算法分析

算法分析关系的是基于所使用的计算资源比较算法。计算资源究竟是什么,一是算法在解决问题时要占用的空间或内存,另一种是算法的执行时间运行时间

  • 时间维度:执行算法所消耗的时间,通常用时间复杂度来描述。
  • 空间维度:执行算法需要占用多少内存空间,通常用空间复杂度来描述。

时间复杂度不是用来计算程序具体耗时的,空间复杂度也不是用来计算程序实际占用的空间的。它们只是量化了算法的操作或步骤。

时间复杂度

时间复杂度使用数量级(order of magnitude),常被称为O 记法来表示(O 指 order),即 T(n) = O(f(n))

n,通常称为问题的规模

***f(n)***,表示每行代码执行次数之和

***T(n)***,表示解决问题所需时间

O,表示正比例关系

这个公式的全称是:算法的渐进时间复杂度

举个例子:

T(n) = 1 + n,随着 n 越来越大,常数 1 对最终结果的影响越来越小,可以直接舍去,直接说执行时间是 O(n)

再举个例子:

T(n) = 5n2 + 27n + 1005,当 n 很小时,常数 1005 时在这个函数中起决定性作用的部分,但随着 n 增长,n2 变的更为重要,n 很大时,包括 27n1005 和 系数 5 的作用都不显著了,因此可以说,函数 T(n) 的数量级是 f(n)=n2 ,或直接说是 O(n2)

常见的时间复杂度量级(上至下依次的时间复杂度越来越大,执行的效率越来越低):

f(n)名称
1常数
logn对数
n线性
nlogn线性对数
n2平方
n3立方
nkK 次方
2n指数

一个时间复杂度为 O(n) 例子:

for(i=0; i<n; ++i)
{
   j++
}

一个时间复杂度为 O(n2) 的例子:

for(i=0; i<n; ++i)
{
   for(j=0; j<n; ++j)
   {
       
   }
}

一个时间复杂度为 O(nlogn) 的例子:

for(i=1; i<n; i++)
{
    j = 1;
    while(j<n)
    {
        j = j * 2;
    }
}

空间复杂度

空间复杂度是对一个算法在运行过程中临时占用存储空间大小的一个量度,同样反映的是一个趋势,记做 ***S(n) = O(f(n))***,空间复杂度比较常用的有:O(1)O(n)O(n²)

一个算法在计算机存储器上所占用的存储空间,包括存储算法本身所占用的存储空间,算法的输入输出数据所占用的存储空间和算法在运行过程中临时占用的存储空间这三个方面。算法的输入输出数据所占用的存储空间是由要解决的问题决定的,是通过参数表由调用函数传递而来的,它不随本算法的不同而改变。

一个算法的空间复杂度只考虑在运行过程中为局部变量分配的存储空间的大小,它包括为参数表中形参变量分配的存储空间和为在函数体中定义的局部变量分配的存储空间两个部分。若一个算法为递归算法,其空间复杂度为递归所使用的堆栈空间的大小,它等于一次调用所分配的临时存储空间的大小乘以被调用的次数(即为递归调用的次数加1,这个1表示开始进行的一次非递归调用)。

举个例子:

int i = 1;
int j = 2;
++i;
j++;
int m = i + j;

纵然代码中为变量 ijm 都分配了内存,但是程序的临时空间不随着某个变量 n 的大小而变化,所以它的空间复杂度为 S(n) = O(1)

再举一个例子:

int[] tmp = new int[n]
for(i=1; i<=n; ++i)
{
    // Empty Body
}

纵然代码中有一个循环,但这个循环并没有分配新的内存,只是再代码第一行 new 了一个数组出来,且这个数组占用的大小为 n,所以它的空间复杂度为 S(n) = O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

二流人物

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

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

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

打赏作者

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

抵扣说明:

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

余额充值