数据结构-什么是算法?

来源:互联网 发布:敬游软件 编辑:程序博客网 时间:2024/06/05 23:52

1.2什么是算法?

算法(Algorithm)
5大特征:

例1:选择排序算法的伪码描述
List到底是数组还是链表(虽然看上去像是数组)
Swap用函数还是用宏去实现?
空间复杂度S(n):Space 执行时占用存储单元的长度。这个长度往往与输入的数据的规模有关,过高可能导致内存超限,造成程序中断。
时间复杂度T(n):Time 执行时消费时间的长度,这个长度往往也与输入的数据的规模有关。时间过长,不好。
上一讲中递归函数的空间占用率S(n)= c *n 会随着n的增长而增长,但是for循环直接输出,占用的空间是一定的,不会随n的增长变化,所以,递归就爆掉了。
上一讲中,求多项式的和,原因是机器运行加减法的速度比乘除法快很多,第一个我们进行了(n2+n)/2次乘法,T(n)=Cn2+cn,第二个程序进行了n次乘法,T(n)=Cn。当很大n2

复杂度的渐进表示法

一、大O记号
存在两个正整数c和n0,使得n>n0的时候,T(n) < c * f(n),则T(n)=O(f(n)),可见O(f(n))可以表示算法运行时间的上界。O(f(n))表示的函数集合的函数是阶数不超过f(n)的函数。

二、Ω记号 读作大 o mi ga
Ω记号与大O记号相反,他可以表示算法运行时间的下界。Ω(g(n))表示的函数集合的函数是所有阶数超过g(n)的函数。

三、Θ记号 读作大si a ta
Θ记号介于大O记号和Ω记号之间。T(n)=Θ(h(n))。表示T(n)=O(h(n))且T(n)=Ω(h(n)),他表示所有阶数与h(n)相同的函数集合。

四、小o记号
f(n)=o(g(n))当且仅当f(n)=O(g(n))且f(n)≠Ω(g(n))。也就是说小o记号可以表示时间复杂度的上界,但是一定不等于下界。

上界和下界不是唯一的。但是太大的上界和太小的下界意义不大,所以尽可能逼近。下面展示:
这里写图片描述
log n 已经不需要注意以什么为底了。
n2的一般都要降到n log n,作为一个专业的程序员。
这里写图片描述
算法复杂度分析的技巧

这里写图片描述

最大子列和问题

例:给定N个整数的序列{A1,A2 An},求函数 这里写图片描述的最大值。
算法1:最直接最暴力的,全算一遍

int MaxSubseqSum1(int A[] ,int N ){    int ThisSum,MaxSum = 0;    int i,j,k;    for(i=0;i<N;i++){     /*i是子列左端位置*/        for(j=i;j<N;j++){ /*j是子列右端位置*/            ThisSum=0;   /*This 表示从A[i]加到A[j]的子列和*/            for(k=i;k<=j;k++)                ThisSum +=A[k];                if(ThisSum > MaxSum)                    MaxSum = ThisSum;        }    }    return MaxSum;}

这个算法的T(n) = O(N3) , 如果三层循环都是0到N的,那么三个相乘,就是N3
优化1、这个算法表示 j 加 1 时,从 i 加到 j, j 再加 1 时,再从 i 加到 j,其实没必要重复计算了,应该在第一次的从 i 加到 j 的前提下,在加一个 j 就好了。所以K循环根本是没必要的。so…..

int MaxSubseqSum2(int A[] ,int N ){    int ThisSum,MaxSum = 0;    int i,j,k;    for(i=0;i<N;i++){     /*i是子列左端位置*/        ThisSum=0;    /*This 表示从A[i]加到A[j]的子列和*/        for(j=i;j<N;j++){ /*j是子列右端位置*/            ThisSum += a[j];             /*对于相同的i,不同的j,只要在j-1的基础上,加上A[j]就可以了*/            if(ThisSum > MaxSum)                MaxSum = ThisSum;    }    return MaxSum;}

因为有两层循环的嵌套 , 所以T(n) = O( n2 )

优化2:一个专业的程序员发现一个算法是n2的时候,下意识的本能的想到能不能变成 nlog n的形式 。so…
这个算法有很大的一个思想:分而治之,把一个大的问题,切分成小块,分头处理它们,最后再把结果合起来就行了。
第一步:分,一份为儿。递归的解决左右的问题,得到左右两边最大的子列和,还有一种跨越边界的最大子列和,我们就可以说最大的数就是其中的一个。
递归的算法。时间复杂度分析有一些难度。
这里写图片描述

但这仍然不是最快的算法~~~~so….

算法4:在线处理

int MaxSubseqSum4(int A[], int N){    int ThisSum,MaxSum;    int i;    ThisSum = MaxSum = 0;    for(i = 0;i<N;i++){        ThisSum += A[i];   /*向右累加*/        if(ThisSum>MaxSum)            MaxSum = ThisSum;   /*发现更大和则更新当前结果*/        else if(ThisSum < 0 )            ThisSum = 0;/*如果子列和为负,则不可能是后面的不分和增大,抛弃之*/    }    return MaxSum;}

T(N) = O(N) 一个算法的运算效率这么高,也是有副作用的,也就是说,别人理解这个程序是怎么工作的不是很明显。
”在线“的意思就是指没输入一个数据就进行即使处理吗在任何一个地方终止输入,算法都能正确给出当前的解。

0 0
原创粉丝点击