数据结构初探

问题抛出:

程序的本质:解决实际问题的步骤描述(前提:理解实际问题)

 如何判断求解问题步骤的好坏

  1)用尽量少的时间解决问题

  2)用尽量少的步骤解决问题

  3)用尽量少的内存解决问题

  案例分析:

 1 //问题:给定一个整数 n,编程求解 1 + 2 + 3 + ... + n 的和。
 2 
 3 #include <iostream>
 4 
 5 using namespace std;
 6 
 7 long sum1(int n)
 8 {
 9     long ret = 0;
10     int* array = new int[n];
11     
12     for(int i=0; i<n; i++)
13     {
14         array[i] = i + 1;
15     }
16     
17     for(int i=0; i<n; i++)
18     {
19         ret += array[i];
20     }
21     
22     delete[] array;
23     
24     return ret;
25 }
26 
27 long sum2(int n)
28 {
29     long ret = 0;
30     
31     for(int i=1; i<=n; i++)
32     {
33         ret += i;
34     }
35     
36     return ret;
37 }
38 
39 long sum3(int n)
40 {
41     long ret = 0;
42     
43     if( n > 0 )
44     {
45         ret = (1 + n) * n / 2;
46     }
47     
48     return ret;
49 }
50 
51 int main()
52 {
53     cout << "sum1(100) = " << sum1(100) << endl;
54     cout << "sum2(100) = " << sum2(100) << endl;
55     cout << "sum3(100) = " << sum3(100) << endl;
56     
57     return 0;
58 }
59 
60 /* 程序效率初步分析:(详解请见后续的 事前分析估算法 )
61     方法1-sum1(): 开辟堆空间(内存有可能申请失败),且使用了两层for循环(最差)
62     方法2-sum2():一层 for循环(一般)
63     方法3-sum3():等差数列公式,一行语句,执行效率高,不会随着项数n的增加,降低程序的执行效率;(较好)
64 */
求解 1 + 2 + 3 + ... + n 的和

数据结构的研究范围:解决非数值计算类型的程序问题;具体包括数据间的组织和操作方式数据的逻辑结构和存储/物理结构

1 数据结构中的新概念

  什么是数据?---- 数据就是程序操作的对象,用于描述客观的实物。

  数据的特点:1) 可以输入到计算机中;2)可以被计算机程序处理

  数据的新概念:

    数据元素:组成数据的基本单位

    数据项:一个数据元素由多个数据项组成

    数据对象:性质相同的数据元素

    ps:数据 ⊇ 数据对象 ⊇ 数据元素 ⊇ 数据项

                     

  数据结构:数据对象数据元素之间的关系。 // 如上例中,Student sArray[10]的每个元素在内存中都是线性存储的。

          或者 相互之间存在特定关系的数据元素的集合

       或者 静态的描述数据元素之间的关系

  数据结构包括:逻辑结构 和 物理结构;

  逻辑结构:

    集合结构:数据元素之间没有特别的关系,仅同属于相同的集合中;

    线性结构:数据元素之间是一对一的关系;

    树形结构:数据元素之间存在一对多的层次关系;

    图形结构:数据元素之间存在多对多的关系;

               

  物理结构:逻辑结构在计算机中的存储结构;

    1) 顺序存储结构:将数据存储在地址连续的存储单元中;(数组)

    2) 链式存储结构:1. 将数据存储在任意的存储单元中;2.通过保存地址的方式找到相关联的数据元素;(链表)

2 初识程序的灵魂

  高效的程序需要在数据结构的基础上设计和选择算法

  算法是特定问题求解步骤的描述;

  对于算法而言,语言不重要,思想才重要

  算法的特性:1)2)3)4)5)基本特性        7)8)9)附加特性

    1)输入:算法具有0个或多个输入;

    2)输出:算法至少有1个或多个输出;

    3)有穷性:算法在可接受的时间内自动结束;

    4)确定性:算法中的每一步都有确定的含义,不能出现二义性

    5)可行性:算法的每一步都是可行的

    6)正确性:(基本准则)

      1. 算法对于合法数据能够得到满足要求的结果;

      2. 算法能够处理非法输入,并得到合理的结果;

      3. 算法对于边界数据压力数据都能得到满足要求的结果;

    7)可读性:算法要求方便阅读,理解和交流;

    8)键壮行:算法不应该产生莫名其妙的结果;

    9)性价比:利用最少的资源得到满足要求的结果;

  程序 = 数据结构 + 算法

  程序的灵魂:算法

  算法为了解决实际问题而存在;数据结构是算法处理问题的载体;数据结构与算法相辅相成,共同解决问题;

3 算法效率的度量方法

  请思考:如果两个算法都可以同时满足功能性需求,此时在工程中最关心算法的性价比附加特性;

  一般来说,算法效率的度量包括:事后统计法  与  事前分析估算法

  1)事后统计法

    概念:比较不同算法对同一组输入数据的运行处理时间;

    缺点:1. 为了获取不同算法的运行时间,必须编写相应的程序;

       2. 运行时间严重依赖硬件 和 运行时的环境因素;

         3. 算法的测试数据很难选取;

  2)事前分析估算法

    概念:依据统计的方法算法效率进行估算

    影响算法效率的主要因素:

      1. 算法采取的策略和方法;

      2. 问题的输入规模;(接下来会重点介绍)

      3. 编译器所产生的代码;(如C++比JAVA生成的可执行程序执行效率高)

      4. 计算机的执行速度;

    使用  事前分析估算法 对数列的前n项和 进行算法效率的简单估算(累计每个算法的执行步骤)  :<--查看数列的前n项和代码-->

           

      在3种求和算法种,sum1()中的关键部分的操作数量为 2n 次;sum2()中的关键部分的操作数量为 n 次;sum3()中的关键部分的操作数量为 1 次;

      关键部分:除去程序的必要开销所留下的部分;

      结论:随着问题的输入规模n逐渐增大,他们之间的操作数量差异也会越加明显,因此,实际算法在效率上的差异也会更加明显。

           通常,对于某个算法,当问题的输入规模n增大时,他会优于另一算法,或者越来越差于另一算法。

      方式1:通过可视化展示上述数列求和算法的执行效果:

       

 1 from pyecharts import Line
 2 
 3 n=21
 4 acount = [i for i in range(1, n)]
 5 scale1 = [2*i for i in range(1, n)]
 6 scale2 = [i for i in range(1, n)]
 7 scale3 = [1 for i in range(1, n)]
 8 
 9 line = Line("不同算法的操作数目对比")
10 
11 line.add("scale1(2*n)", acount, scale1, xaxis_type='value')
12 line.add("scale2(n)", acount, scale2, xaxis_type='value')
13 line.add("scale3(1)", acount, scale3, xaxis_type='value', xaxis_name='问题输入规模n', yaxis_name='算法实际操作数量')
14 
15 line
上图可视化代码展示:

     方式2:通过表格对比不同算法的执行效率;

       

    结论:n == 1时,算法C( 2n2+3n+1 )和算法D( 2n3+3n+1 )的操作数量相同;当n越来越大的时候,算法C ( 2n2+3n+1 )的效率远高于算法D ( 2n3+3n+1 );

      

     结论:判断一个算法的效率时,操作数量中的常数项和其他次要项常常可以忽略,只需要关注最高阶项就能得出结论。

       

 

posted @ 2020-02-20 22:38  PRO_Z  阅读(233)  评论(0编辑  收藏  举报