您的位置:首页 > 理论基础 > 数据结构算法

数据结构的学习(2)(c语言)

2016-03-19 17:48 295 查看
上一章只是一个简介,对于数据结构的简短介绍,所以在难度上可能并不是那么难,不过从这一章开始,难度就会有明显的提升了

2,算法

其实,算法就是我们为了解决我们在编程中遇到的问题,而打出的一连串操作指令,其中.每一个或是几个指令会去完成我们给他赋予的功能,这就是算法,算法具有五个基本特性,分别是输入,输出,有穷性,确定性,可行性

(1),输入,输出

在算法中,输入可以是零个,就像是我们刚开始接触c语言时,自己编写的最简单的程序,打印hello world,这个程序并不需要你的输入,但是算法必须有输出,没有输出的算法没有利用价值

(2),有穷性

你编写的代码,必须要有穷,也就是不能一直循环下去,并且循环要在一个可接守的时间内结束,

(3),确定性

算法的每一步骤都要有其唯一的意义,不能有歧义

(4),可行性

算法的每一步都必须可行,每一步都在可接受的有限次数完成,因为受限与编程工具和人的大脑,这条是必须的

我们对算法设计的要求,应该满足一下几点,首先,算法必须准确无误,首先,算法不能有语法错误,其次,对于我们输入的数据,算法应该有正确的输出来响应我们的输入,而在这一点中,我们输入的数据,应该从简单的符合条件的数据,到不符合条件的数据,再到某些极其刁钻的数据,都应该有一个正确的输出

(5),可读性

便于理解和阅读,可以让人们相互交流

(6),健壮性

当输入的数据不合法时,算法也能根据事先编好的代码,来做出指示,而不是输出一堆没用的数据,

(7),时间效率高,存储量低

顾名思义,一个好的算法,应该具备工作效率高,并且在系统中所占的存储量也低的特点

我们要估计一个算法的效率,大部分情况下都是度量算法工作的时间,算法的度量方法又分为以下几种

1,事后统计方法

根据设计好的程序和数据,用计时器来对不同算法的工作时间进行比较,最后得出工作效率的高低

缺点:

必须根据已经编好的程序来进行比较,如果程序本身就是错误的,那么这种方法就会很差

时间的比较依赖于计算机的型号不同和操作系统等等因素,有可能这些因素会干扰对于算法效率的判断

测试数据设计困难,例如计算十几个数据的操作比较,差异几乎没有,但是如果是成千上万的数据,差距就会很大

基于以上特点,事后统计方法不予考虑

2,事前统计方法

既然事后统计方法不予考虑使用,那么我们就使用事前统计方法来比较算法的效率,所谓事前统计方法,就是在程序编译前,依据统计方法来对算法进行估算,经过分析,我们得出程序在计算机的消耗时间取决于以下几个因素

1,算法采用的策略,方法

2,编译产生的代码质量

3,问题的输入规模

4,机器执行指令的速度

有几条因素是和算法以外的东西有关,例如编译器的选择,硬件的响应速度等等,除此之外,程序的运行时间依赖于算法的好坏和问题输入的规模,所谓问题输入的规模,也就是输入量的大小

在分析算法的运行时间时,重要的是把基本操作的数量与输入规模关联起来,基本操作的数量必须表示成输入规模的函数

函数的渐进增长

假设有两个算法,输入规模都是n,一个算法要执行2n+2次操作,另一个要执行3n+1操作,这两个算法哪个效率更高呢?其实答案并不一定,我们可以把n带入从1到n的数字看看,这两个的大小关系并不是一成不变的,在n大于1时,a的操作效率是大于b的,所以我们给出定义,输入规模在没有限制时,只要超过一个数字n,这个函数总是大于另一个函数,我们称函数是渐进增长的.

函数的渐进增长:给定两个函数f(n)和g(n),如果存在一个整数N,在n>N的情况下,f(n)恒>g(n),我们就说,f(n)的渐进增长快于g(n)

算法的时间复杂度

在进行算法分析时,语句总的执行次数T(n)是关于问题规模n的函数,算法的时间复杂度,也就是算法量度,记作T(n)=O(f(n)),表示随着问题规模的增大,算法执行时间的增长率和f(n)的增长率相同乘坐算法的渐进时间复杂度,简成为时间复杂度,f(n)是关于问题规模的一个函数

用大写o来表示算法时间的复杂度,我们称为大o记法,一般随着时间的增长,T(n)增长的最慢.是最优算法,算法的时间复杂度有一下几种比较主要的,像是O[1](常数阶),O
(线性阶),O[n^2](平方阶)

如何分析一个算法的大O阶呢?

首先,我们先用1取代所有算法中出现的加法常数,在修改后的次数函数后,只保留最高阶项,并且让最高阶项前面的常数变成1,得到的就是这个算法的大O阶

说起来很容易,但是实际计算的时候,有可能算错,像是以下这几行代码

int i;

scanf("%d",&i);

printf("%d",i);

让你去计算一下大O阶,很有可能我得到的答案是3,因为执行了3次吗,但是,3只是算法的运行函数,我们推导大O阶,首先就要把常数化成1,所以这个算法的大O阶是1,也就是常数阶

如果我们把上面这行代码的printf执行10次,或者是100次,因为执行的次数和n无关,所以,我们把这种算法的时间复杂度统称为O[1],也就是常数阶(注意,常数阶必须写成O(1),里面必须是1)

像是

int i;

for(i=0,i<n,i++)这段代码的时间复杂读就是O(n),线性阶

这种

int cou;

while cou<n;

{ n=n*2;

} 这样代码的问题规模函数式是f(n)=log2 n,所以时间复杂度是O[logxN].对数阶

循环嵌套的时间复杂度一般是前者外层乘以里层,如果两个循环结构是平行结构,那么问题规模函数就是俩个时间复杂相加,当然,具体问题我们要具体分析

ps: 附上时间复杂度的表格

执行次数函数 阶 非正式术语

12 O(1) 常数阶

2n+3 O(n) 线性阶

3n^2+2n O(n^2) 平方阶

2log2n O(logn) 对数阶

2nlog2n O(nlogn) nlogn阶

3n^3 O(n^3) 立方阶

2^n O(2^n) 指数阶

所耗费的时间大小分别是 常数阶<对数阶<线性阶<nlogn阶<平方阶<立方阶<指数阶<O(n!)(阶乘阶)<O(n^n)(我也不知道是什么阶)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: