【数据结构与算法】-02算法和算法分析

目录

1.算法

1.1定义

1.2算法的描述

1.3程序与算法

1.4算法的特性

1.5算法的设计要求

2.算法分析

2.1算法的时间复杂度

2.1.1语句频度

2.1.2渐进时间复杂度

2.1.3分析算法时间复杂度的基本方法

2.1.4常数阶

2.1.5线性阶

2.1.6对数阶

2.1.7平方阶

2.1.7立方阶

2.1.8最好、最坏和平均时间复杂度

2.1.9计算公式

2.2算法的空间复杂度

2.3时间与空间的取舍


1.算法

1.1定义

解决问题的方法和步骤。在计算机中表现为指令的有限序列。其中每条指令表示一个或多个操作。

1.2算法的描述

自然语言;流程图【NS图、框图】;伪代码(类C语言);程序设计(C、Java...)

类C语言介于伪码语言和程序设计语言之间的一种表示形式,保留了C语言的精华,不拘泥于C语言的语法细节,同时也添加了一些C++的成分。特点:便于理解,阅读能方便的转换成C语言

1.3程序与算法

程序=数据结构+算法

数据结构通过算法来实现操作

算法根据数据结构设计程序

1.4算法的特性

(确定、有穷、可行、输入、输出)

1.有穷性:算法在执行有限步骤之后,自动结束而不会出现无限循环,并且每一个步骤都在可接受的时间范围内完成。当然这里的有穷并不是纯数学意义的,而是在实际应用中合理的、可以接受的“边界”。你说你写一个算法,计算机需要算上20年,一定会结束,他在数学上是有穷的,媳妇都熬成婆了,算法的意义

就不大了。

2.确定性:算法的每一个步骤都有确定的含义,不会出现二义性(不会有歧义)。

3.可行性:算法中的所有操作都可以通过已经实现的基本操作运算执行有限次来实现。

4.输入:一个算法有零个或多个输入。当用函数描述算法时,输入往往是通过形参表示的,在它们被调用时,从主调函数获得输入值。

5.输出:一个算法有一个或多个输出,它们是算法进行信息加工后得到的结果,无输出的算法没有任何意义。当用函数描述算法时,输出多用返回值或引用类型的形参表示。

1.5算法的设计要求

好的算法应该具有正确性、可读性、健壮性、时间效率高和存储量低的特征。

1.正确性(Correctness):能正确的反映问题的需求,能得到正确的答案。

分以下四个层次:

a.算法程序没有语法错误;

b.算法程序对n组输入产生正确的结果;

c.算法程序对典型、苛刻、有刁难性的几组输入可以产生正确的结果;

d.算法程序对所有输入产生正确的结果;

但我们不可能逐一的验证所有的输入,因此算法的正确性在大多数情况下都不可能用程序证明,而是用数学方法证明。所以一般情况下我们把层次3作为算法是否正确的标准。

2.可读性(Readability):算法,首先应便于人们理解和相互交流,其次才是机器可执行性。可读性强的算法有助于人们对算法的理解,而难懂的算法易于隐藏错误,且难于调试和修改。

3.健壮性(Robustness):当输入的数据非法时,好的算法能适当地做出正确反应或进行相应处理,而不会产生一些莫名其妙的输出结果。【健壮性又叫又名鲁棒性即使用棒子粗鲁地对待他也可以执行类似于Java预料到可能出现的异常并对其进行捕获处理】

4.(高效性)时间效率高和存储量低

2.算法分析

算法分析的目的是看算法实际是否可行,并在同一问题存在多个算法时可进行性能上的比较,以便从中挑选出比较优的算法。

时间效率(运行时间的长短)和空间效率(占用内存空间的大小)是衡量算法好坏的重要因素

2.1算法的时间复杂度

衡量算法时间效率的方法主要有两类:事后统计法和事前分析估算法。

事后统计法需要先将算法实现,然后测算其时间和空间开销。

这种方法的缺陷很显然:

一是必须把算法转换成可执行的程序,如果编辑出来发现它根本是很糟的算法,不是竹篮打水一场空吗?

二是时空开销的测算结果依赖于计算机的软硬件等环境因素,这容易掩盖算法本身的优劣。

三是算法的测试数据设计困难,并且程序的运行时间往往还与测试数据的规模有很大关系,效率高的算法在小的测试数据面前往往得不到体现。比如10个数字的排序,不管用什么算法,差异几乎是零。而如果有一百万个随机数字排序,那不同算法的差异就非常大了。那么我们为了比较算法,到底用多少数据来测试,这是很难判断的问题。所以我们通常采用事前分析估算法。

2.1.1语句频度

一个算法的执行时间大致上等于其所有语句执行时间的总和,而语句的执行时间则为该条语句的重复执行次数和执行一次所需时间的乘积。

一条语句的重复执行次数称作语句频度(FrequencyCount)。

语句的执行要由源程序经编译程序翻译成目标代码,目标代码经装配再执行,因此语句执行一次实际所需的具体时间是与机器的软、硬件环境(如机器速度、编译程序质量等)密切相关的。

设每条语句执行一次所需的时间均是单位时间,则一个算法的执行时间可用该算法中所有语句频度之和来度量

所谓的算法分析并非精确统计算法实际执行所需时间,而是针对算法中语句的执行次数做出估计,从中得到算法执行时间的信息。

求两个n阶矩阵的乘积算法

【i从1~n首先判断条件是否成立,条件满足执行循环体并i++,i=n+1判断条件是否成立条件不满足,退出循环,判断n+1次循环体执行了n次】

2.1.2渐进时间复杂度

对于稍微复杂一些的算法,计算出算法中所有语句的频度通常是比较困难的。

通常,算法的执行时间是随问题规模增长而增长的,因此对算法的评价通常只需考虑其随问题规模增长的趋势。

这种情况下,我们只需要考虑当问题规模充分大时,算法中基本语句的执行次数在渐近意义下的阶

基本语句:执行次数最多;对算法运行时间贡献最大;嵌套最深的语句。

2.1.3分析算法时间复杂度的基本方法

1.找出语句频度最大的那条语句作为基本语句;

2.计算基本语句的频度,得到问题规模n的某一个函数;

3.取其数量级用O表示

忽略所有低次幂项和最高次幂的系数,这样可以简化算法分析,也体现出了增长率的含义。

2.1.4常数阶

实际上,如果算法的执行时间不随问题规模n的增加而增长,算法中语句频度就是某个常数。即使这个常数再大,算法的时间复杂度都是O(1)。

2.1.5线性阶

给小灰一个长度为10cm的面包,小灰每三分钟吃掉1cm,那么他吃掉整个面包要多久?

答案自然是3*10=30min

如果面包的长度为n cm呢?

此时吃掉整个面包需要3*n即3n分钟。

如果用一个函数来表达吃掉整个面包所需要的时间可以记作T(n)=3n(n表示面包的长度即处理的数据的规模)

2.1.6对数阶

2.1.7平方阶


由于当i=0时内循环执行n次,当i=1时内循环执行n-1次,...,当i=n-1时内循环执行1次总执行次数

n+(n-1)++(n-2)+...+1=n(n+1)/2

时间复杂度是O(n^2)

2.1.7立方阶

不太知道怎么算可以复习下级数求和


2.1.8最好、最坏和平均时间复杂度

有的情况算法的基本操作重复执行的次数还随问题输入的数据集不同而不同


最好的情况a0=e执行1次

最坏数组中没有e/an-1=e执行n次

而对于一个算法来说,需要考虑各种可能出现的情况,以及每一种情况出现的概率,一般情况下,可假设待查找的元素在数组中所有位置上出现的可能性均相同。类似于数学中求期望值。计算每一种情况执行次数与概率的乘积在求和。

最坏时间复杂度是指在最坏情况下算法的的复杂度;

最好时间复杂度是指在最好情况下算法的的复杂度;

平均时间复杂度是指算法在所有可能情况下,按照输入实例以等概率出现时,算法计算量的加权平均值。

通常考虑最坏和平均但有时平均比较难计算只考虑最坏时间复杂度,最坏情况运行时间是一种保证,那就是运行时间不会再坏了。

2.1.9计算公式

如果时间复杂度是平方阶最好降低到对数阶实在不行平方阶也可以接受,立方阶也尚可。

2.2算法的空间复杂度

算法的空间复杂度是算法要占据的空间

算法本身要占据的空间:输入/输出、指令、常数、变量等。

算法要使用的辅助空间。

若输入数据所占据的空间只取决于问题本身和算法无关,这样只需分析该算法在实现时所需的辅助单元即可,若算法执行时所需的辅助单元相对于输入数据量而言是个常数,则称此算法为原地施工,空间复杂度为O(1)


2.3时间与空间的取舍

人们之所以花大力气去评估算法的时间复杂度和空间复杂度,其根本原因是计算机的运算速度和空间资源是有限的。就如一个大财主,基本不必为日常的花销而伤脑筋,而一个没有多少积蓄的普通人则不得不为日常的花销精打细算。对于计算机系统来说也是如此,虽然目前计算机的CPU处理速度不断飙升,内存和硬盘空间也越来越大,但是面对庞大而复杂的数据和业务,我们仍要精打细算,选择最有效的利用方式。

举个例子说,要判断某年是不是闰年,你可能会花一点心思来写一个算法,每给一个年份,就可以通过这个算法计算得到是否闰年的结果。

另外一种方法是,事先建立一个有2050个元素的数组,然后把所有的年份按下标的数字对应,如果是闰年,则此数组元素的值是1,如果不是元素的值则为0。这样,所谓的判断某一年是否为闰年就变成了查找这个数组某一个元素的值的问题。

第一种方法相比起第二种来说很明显非常节省空间,但每一次查询都需要经过一系列的计算才能知道是否为闰年。第二种方法虽然需要在内存里存储2050个元素的数组,但是每次查询只需要一次索引判断即可。

这就是通过一笔空间上的开销来换取计算时间开销的小技巧。到底哪一种方法好?其实还是要看你用在什么地方。但在绝大多数情况下,时间复杂度更重要一些,我们宁愿多分配一些内存空间也要提升程序的执行速度。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

闪耀大叔

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

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

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

打赏作者

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

抵扣说明:

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

余额充值