(第二章)知识点:数据结构与算法

1、引入

凭借一句话获得图灵奖的Pascal之父——Nicklaus Wirth,让他获得图灵奖的这句话就是他提出的著名公式:“算法+数据结构=程序”。

2、算法

解决问题的方法(广义)

(1)算法的特点:

1)有效性;

2)可行性;

  对于浮点数(科学计数法),考察这样的问题:

  3e18 + 3e-18

  这个运算在很多计算机系统中,是不可行的。

3)有限步骤;

4)至少有一个输出;

5)稳定性(可重现性)。

解决问题的方法绝对没有唯一性(没有标准答案);但是,解决问题的方法之间是可以进行比较,比较的是性能等方面。在讨论某种算法性能时会发现,没有任何一个算法能成为“完美”的!任何算法都有优、缺点(世界上没有单面的硬币)。

​​​​​​​(2)衡量算法性能指标

衡量算法性能指标有两个:1)时间复杂度;2)空间复杂度。

1)时间复杂度:问题规模和解决该问题所执行的基本指令的次数(量)的函数关系。

 

eg1.关于数据逆置的方法:

有一组数据,要求逆置这些数据。或者说,有数组int  arr[10],并赋初值,要求编程实现对该数组元素的逆置。

方法1:

准备临时数组int  temp[10];从后向前地将arr数组的元素,存储到temp数组中:

for(i  =  0;  i  <  10;  i++){

     temp[i]  =  arr[10-i-1];

}

分析:ar[0]  ->  temp[9]

          ar[1]  ->  temp[8]

          ar[2]  ->  temp[7]

          ar[3]  ->  temp[6]

          ar[4]  ->  temp[5]

          ar[5]  ->  temp[4]

          ar[6]  ->  temp[3]

          ar[7]  ->  temp[2]

          ar[8]  ->  temp[1]

          ar[9]  ->  temp[0]

 

          ar[i]  ->  temp[10-1-i]

 

然后,再将逆置了的,但是存储于temp数组中的数据,再放回到arr数组:

for(i  =  0;  i  <  10;  i++){

     arr[i]  =  temp[i];

}

 

总共需要2倍的10次运算;若原数组中的数据个数是n个,那么,需要的基本操作次数是2*n次,可以写成:O(2n)

(当n趋向于无穷大时,其与O(n)同阶无穷大),于是,可以说,这个算法的时间复杂度是:O(n)。

另外,这个算法需要n个元素的临时空间,因此,空间复杂度为O(n)。

 

方法2:

将数组中,按中轴对称的元素“对调”,也可以实现逆置:

int  tmp;

for(i  =  0;  i  <  10/2;  i++){

     tmp  =  arr[i];

     arr[i]  =  arr[10-i-1];

    arr[10-i-1]  =  tmp;

}

上述操作需要10/2次循环(基本操作);若原数组中的数据个数是n个,那么,其时间复杂度是:O(n/2);空间复杂度为O(1)

(这个O(1)的意思是,辅助空间的大小,与问题规模(就是数组数据个数)无关)。

见博客:。。。。。。。。。。。。

 

eg2.课堂小练习:要求计算n以内的正整数之和,假设n在10万到1亿之间(不考虑int取值范围溢出问题)。

方法1;

int i;

int sum = 0;

for(i = 0; i < n; i++)

     sum += i;

printf(“%d\n”, sum);

上面的程序的时间复杂度是O(n)。

 

方法2:

printf(“%d\n”, (1+n)*n/2);

这段具有相同功能的算法,时间复杂度是O(1)。

 

对于时间复杂度的基本计算规则:

时间复杂度主要体现在循环的循环次数;

多重嵌套循环,时间复杂度是各层循环的循环次数之积!

并列多个循环,时间复杂度是各个循环的循环次数之和!

具体的说,要进行“变量跟踪”才能真正的搞清楚时间复杂度问题。

 

eg3.

for(a = 0; a < 100; a++)

     for(b = 0; b < 100; b++)

         for(c = 0; c < 100; c++)

                …

很简单,时间复杂度为O(n^3)

 

eg4.

for(a = 0; a < 100; a++)

      for(b = a+1; b < 100-a; b++)

              …

分析(变量跟踪):

当a为0时,内层循环:for(b = 1; b < 100; b++),即,99次;

当a为1时,内层循环:for(b = 1+1; b < 100-1; b++),即,99-2次;

当a为2时,内层循环:for(b = 1+2; b < 100-2; b++),即,99-4次;

当a为3时,内层循环:for(b = 1+3; b < 100-3; b++),即,99-6次;

当a为49时,内层循环:for(b = 1+49; b < 100-49; b++),即,1次;

共50轮;即,总循环次数是:1+3+5+ … + 99=>O((n/2)^2)=>O(n^2)

猜你喜欢

转载自blog.csdn.net/weixin_42072280/article/details/82954123
今日推荐