1 / 41

第一章 绪 论

第一章 绪 论. 1 、历史沿革 2 、计算机科技的两大支柱 3 、数据类型和数据结构 4 、算法 5 、时间复杂性的度量 6 、有效算法的重要性. 历史沿革. 1968 年 D·E·Knuth :“ Art of computer programming” IEEE 68 教程 1983 IEEE 83 教程 1991 IEEE 91 教程 2000 IEEE 2000 教程 国内在 78 年 开设. 计算机科技的两大支柱. · 1 、 数据结构 2 、 算法 · 程序 = 数据结构 + 算法.

Download Presentation

第一章 绪 论

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第一章 绪 论 1、历史沿革 2、计算机科技的两大支柱 3、数据类型和数据结构 4、算法 5、时间复杂性的度量 6、有效算法的重要性

  2. 历史沿革 • 1968年 D·E·Knuth :“ Art of computer programming” • IEEE 68 教程 • 1983 IEEE 83 教程 • 1991 IEEE 91 教程 • 2000 IEEE 2000 教程 • 国内在 78 年 开设

  3. 计算机科技的两大支柱 • · 1、数据结构2、算法 • · 程序 = 数据结构 + 算法 输入未处理的数据 算法 输出加工过的数据

  4. 数据类型和数据结构 • ·数据值:atomic data value: 不可再分解。如3、2、5等。 • non-atomic data value: 可以再分解, • 其成分称为data element 或 element。如 set: { 32.99, -1.03, 0, 23} 。 • ·类型:同一类别可供识别的一组个体。 • ·数据类型:data type = data value + operation 或者定义为 • 1、A set of value • 2、A set of operations on the these value。

  5. 数据类型的类别 • 1、原子数据类型: • 数据值是原子数据值。如:int • 2、结构数据类型: • 数据值是可以再分解。如:an array[1..3 ] of real • value1 value2 value3 • [1] 0 [1] 1.9 [1] 1.9 • [2] 1.9 [2] 0 [2] 1.9 • [3] 3.4 [3] 3.4 [3] 6.8 • value1 value2 • 数据值的进一步分解为数据元素,它们之间有一个关系。

  6. 数据类型的类别 • 1、原子数据类型: • 数据值是原子数据值。如:int • 2、结构数据类型: • 数据值是可以再分解。如:an array[1..3 ] of real • value1 value2 value3 • [1] 0 [1] 1.9 [1] 1.9 • [2] 1.9 [2] 0 [2] 1.9 • [3] 3.4 [3] 3.4 [3] 6.8 • operation: 1、在 data value上:var value1, value2, value 3; • value3 = value1 + value2; • 2、在 元素上:var value1; • value1 [1] = 1.2;

  7. 数据结构 • 是一种数据类型,其数据值: • 1、可以进一步分解为数据元素的集合,该数据元素可以是原子数据值,也可以是 • 另外一种数据结构。 • 2、数据元素之间有一个关系的集合。 • 注意:在许多数据结构的书籍(课本)之中,通常将数据元素称之为结点 • ·数据结构的分类: • 1、线性结构:如:线性表:空或一个元素或:除第一个结点外,都有直接前驱结点, • 除最后一个结点外,都有直接后继结点。 • 其它如:栈、队列等。 • 2、非线性结构:树、二叉树、图等。

  8. 数据结构的实现 • 1.ADT(Abstract Data Type): • 认为 DT 仅存在于想象之中。注意力集中在感兴趣的性质上,不关心数据的表示形式、操作的具体代码等等。给出规范或说明。 • 2.VDT(Virtual Data Type): • DT 存在于 Virtual processor 上。 • 如: c++ = O.S. + hardware + c++ compiler 的 Virtual processor。其他如 SQL Virtual processor 等 。给出表示和实现。如:用类、类属数据类型、模板等。 • 3.PDT(Physical Data Type): • DT 存在于物理机器上。

  9. 例:线性表 • 在C++中数据结构的构造:以一个线形表为例说明。 线形表实例: 3 22 5 45 23 8

  10. 抽象数据类型 表1.1: 表seqlist 的抽象数据类型(ADT) ADT seqlist is Data一个数据元素的表seqlist,其数据元素或结点可由序号进行标识。 Operations Constructor 构造一个空表。 ListSize 前提:无。 结果:给出表seqlist的规模。 ListEmpty 前提:无。 结果:若表seqlist为空返回True,否则False。 ClearList 前提:无。 结果:若表seqlist非空,则清空表seqlist。 Find 前提:给定数据元素或结点。 结果:若查找成功则返回True, 否则返回False。 Insert 前提: 给定要插入的数据元素。 结果:将该数据元素插入到表seqlist的末尾,表的规模增加1。 Delete 前提: 给定要删除的数据元素之值。 结果:查找该数据值的结点,查找成功则删除之,表seqlist的规模减少1,否则删除失败。 DeleteFront 前提: 表seqlist非空。 结果:删除队首结点并返回结点的数据值,表seqlist的规模减少1。 GetData 前提: 数据元素或结点的位置或序号,其序号在0和表的大小减1之间。 结果:给出相应表seqlist位置序号的结点的数据值。

  11. 虚拟数据类型 表1.2: 用 C++表示的表 seqlist 的规范( VDT ) class seqlist { private: int size;// size of the seqlist. It is 0 when the seqlist is empty. DataType * list; // DataType is the data type of the component elements of seqlist. public: // the seqlist access methods. seqlist( ); int ListSize( ) const; int ListEmpty( ) const; int Find( int & item ) const; DataType GetData(int pos) const; // the seqlist modification method. void Insert( const int & item ); void Delete( const int & item ); void ClearList( ); }; 通常数据结构和算法的教科书,直接给出VDT。

  12. 例:有序表 3 22 5 45 23 线形表实例: 8 3 5 8 22 23 有序表实例: 45 表1.3:有序表orderlist 的抽象数据类型(ADT) ADT orderlist is Data < same as the seqlist ADT > Operations Constructor < executes the base class constructor > ListSize < same as the seqlist ADT > ListEmpty < same as the seqlist ADT > ClearList < same as the seqlist ADT > Find < same as the seqlist ADT > Insert < same as the seqlist ADT > Delete < same as the seqlist ADT > DeleteFront < same as the seqlist ADT > GetData < same as the seqlist ADT > Insert 前提: 给定被插入的数据元素的值。 结果:在表Orderlist中按序插入新的数据元素,且表Orderlist的规模增大1。

  13. 例:有序表 • 有序表的构造,分析和线形表之间的关系:经过分析大部分操作是一样的。 表1.4: 有序表orderlist 的规范 class orderlist : public seqlist { public: orderlist( ); // initialize base class to creat an empty list. int Insert( const int & item ); //insert a new item in order. }; • 通过继承关系,可以很容易得到具有自己特点的数据结构。 • 通过模板,将类型作为参数,可以得到 Generic Data Structures。 • 从而上升到数据结构的更高抽象层次。

  14. 欧几里德算法: • 如果 m、n 都是正整数,且 m > n, 则 m = nq + r , 0 < r < n, 此处 r,q 都是正整数。那么,(m,n) = ( n, r) ; // (a,b ) 为 a、b之间的最大公约数。 • 计算m、n 之间最大公约数的算法: • n if mod(m,n) = 0 • g(n, mod(m,n)) if mod(m,n) != 0 g(m,n) = 算法 • 一个算法就是有穷规则的集合,其中的规则规定了一个解决某一个特定问题的运算序列。

  15. 程序框图: Input m, n 输入 r = mod(m, n) 求余数 output n 求出 m、n 的最大公约数 r = = 0 ? 更新被除数、除数 m = n; n = r 例:欧几里德算法 • 特征: 1、有穷性:执行有穷步后结束。 • 2、确定性:每一步有确定的含义。 • 3、能行性:原则上能精确的进行,用纸和笔有限次完成。 • 4、输入: • 5、输出:

  16. 例:算法实现 算法1.1:求m、n 之间的最大公约数 // 输入两个正整数m、n, 满足关系m > n 。现在要求m 和n 之间的最大公约数。 int maximal_common_divisor( ){ int m,n; int r; // r用于保存m % n 之值。 cout << "Please enter two positive intergers m n ,note: m > n !" << endl; cin >> m >> n; // 输入m 和n 之值。 Exception( m < n, “m <n is ERROR.” ); //若m> n,继续;否则出错,程序中断。 cout << " m is " << m << "!" << " n is " << n << endl; //显示m、n。 while ( 1 ){ r = m % n; // 得到m/n 之后的余数。 if ( r == 0 ) return n; // 若余数为0,那么原m和n之间的最大公约数为n。 else { m = n; // 更新被除数m。 n = r; // 更新除数n。 } } } // 在m > n 时,函数返回正整数m 和n之间的最大公约数。

  17. 时间和空间复杂性的度量 • ·问题的规模(n):如:矩阵的阶数、图的结点个数、被分类序列的正整数个数 • ·时间复杂性:算法的所需的时间和问题规模的函数。记为 T(n)。 • 当 n--> ∞ 时的时间复杂性,被称之为渐进时间复杂性。 • ·空间复杂性:算法的所需的空间和问题规模的函数。记为 S(n)。 • 当 n--> ∞ 时的空间复杂性,被称之为渐进空间复杂性。 • ·程序运行时间:1、 输入规模 • 2、利用编译程序生成的目标代码的质量 • 3、计算机程序指令系统的品质和速度 • 4、算法的时间复杂性的函数 • 1、4 点自明。2、3两点表示算法的时间依赖于软件和硬件的环境。用在某一系统 中的绝对时间秒、分… 作为衡量,判断算法的优劣是不正确的。 • ·最坏情况下的时间复杂性和平均情况下的时间复杂性

  18. 时间复杂性:大 O 表示法 • 定义: 如果存在着正的常数 c 和自然数 n0,当 n ≥ n0时;有 f (n) ≤ c*g(n) 成立,则 称 f( n ) = O(g( n )) 。 • 在算法分析中, 如果一个的算法的时间复杂性是O(g( n )),读作 g( n ) “ 级 ” 的 或 “ 阶 ” 的。 如: 线性阶的、平方阶的、立方阶的 …… • ·例1、 设 T(n) = (n+1)2 • = n2+2n +1 ≤ n2 + 2n2 + n2; 在 n=1 时,等式成立,n>1 时,< 式成立 • 选 n0 = 1, c=4 ; T(n) ≤ 4n2。所以,T(n) = O(n2)

  19. 大 O 表示法 • ·例2、 设 T(n) = 3n3+2n2 • 选 n0 = 0, c=5 ; T(n) ≤ 5n3。所以,T(n) = O(n3) • 同理:选 n0 = 0, c=5 ; T(n) ≤ 5n4。所以,T(n) = O(n4)??? • 注意:符合定义,但在算法分析中是没有意义的。 • 在算法分析中,通常所说的找到了时间复杂性的级别,是指找到了同样级别的最 简单的函数。 • 如:307 n2、n2/2、n2 都是同一级别的函数,最简单的函数是n2。所以, 307 n2、n2/2、n2 的级别都是O(n2 ) 。 • f、g同级别:满足: f = O(g) 且 g = O(f),

  20. 紧贴渐进界 • ·例3、设 T(n) = 3n != O(2n) • 注意: f(n)=O(g(n)) 意味着找到了 f(n) 的一个最“ 紧贴” 的上界 g(n) , 或者说最低的上界。从算法的时间复杂性角度来看,像例2 中的 O(n4) 是没有意义的。 • 紧贴渐进界:设存在一个函数 f(n) = O(g(n)),如果对于每一个函数 h(n): • f(n) = O(h(n))  g(n)=O(h(n)),就说 g(n) 是 f(n) 的紧贴渐进界。 • 例4:f(n)=3n+5;f(n)= O(n) 同样根据定义 f(n)= O(n2) 。但是,f(n) 的 • 紧贴渐进界是f(n)= O(n) ,而不是f(n)= O(n2)。 • 反证法:假设 g(n)=n 不是 f(n)=3n+5的紧贴渐进界(意思即为:g(n)=n 是 • f(n)=3n+5的渐进界,而不是 f(n)=3n+5的紧贴渐进界),那么根据定义对于使得 • f(n)=O(h(n)) 的函数 h(n), g(n) != O(h(n))。 • 设存在函数 h (n),使得 f(n)=3n+5= O(h(n)) ,且g(n) != O(h(n))。由于3n+5= O(h(n)) , • 那么根据大 O 法的定义,必存在正数c和n0,使得对于所有的 n ≥ n0 ,3n+5 ≤ c*h(n)。 • 很显然,对一切 n ≥ 0,有 n ≤ 3n+5 ,所以 g(n) ≤ c*h(n)。 这样,根据大O 法 • 的定义有g(n)=O(h(n)) 。与假设相矛盾。 #

  21. 求和定理 • 求和定理:假定T1(n)、T2(n)是程序P1、P2的运行时间,并且T1(n)是O(f(n))的,而T2(n)是 • O(g(n))的。那么,先运行P1、再运行P2 的总的运行时间是:T1(n)+T2(n)= • O(MAX(f(n),g(n)) 的。 • 证明:根据定义,对于某些常数c1、n1、及c2、n2,由已知可得: • 在n ≥n1 时,T1(n) ≤ c1 f(n) 成立。 • 在n ≥n2 时,T2(n) ≤ c2 g(n) 成立。 • 设n1和n2之间的最大值为n0,即n0 = MAX(n1,n2)。 • 那么,在n ≥ n0时;T1(n) +T2(n) ≤ c1 f(n) +c2 g(n)成立。所以,T1(n) +T2(n) ≤ • (c1+c2 ) MAX(f(n),g(n))。# • 例5. P1、P2、P3三段程序的运行时间分别为O(n2)、O(n3)及O(nlogn) 。那么,先运行P1,再运行P2的运行时间为O(MAX(n2,n3)=O(n3),接着再运行P3的总的运行时间为 • O(MAX(n3,nlog2n)=O(n3)。 • 即若干个程序顺序运行时,其总的运行时间的级别取决于具有最大值的那个函数。

  22. 求积定理 • 求积定理:如果T1(n) 和T2(n)分别是O(f(n))和O(g(n))的,那么T1(n)×T2(n)是O(f(n)×g(n)) 的。 • 证明:已知在n ≥n1 时,T1(n) ≤ c1 f(n) 成立;在n ≥n2 时,T2(n) ≤ c2 g(n) 成立。 • 其中c1、n1、及c2、n2 都是常数。 • 所以,在n ≥ MAX(n1,n2) 时,T1(n)×T2(n) ≤c1c2f(n)g(n), • 因此T1(n)×T2(n)是O(f(n)×g(n)) 的。#

  23. 0 1 2 3 4 5 25 12 47 89 36 14 例:起泡分类法 • ·设例子中数组的规模为: Size = 6 算法1.2: 类模板 seqlist 的用于排序的起泡方法 template < class Type > void seqlist<Type> :: BubbleSort( ) { // 将数组p[0]到p[size-1] 逐趟进行比较,size为表的规模。 int j,k; int flag = 1; // 交换标志,flag 为1 表示出现过数据交换,继续进 //行排序。若flag为0,表示未出现过数据交换,数组 // p[0]到p[size-1]已经排好序,排序结束。 for ( j=0; j <= size - 2 && flag; j++ ){ flag = 0; for ( k = size - 1; k > j; k - -) if ( p[k-1] > p[k] ) { Type temp = p[k-1]; p[k-1] = p[k]; p[k] = temp; flag = 1; } } }

  24. 0 1 2 3 4 5 25 12 47 89 36 14 例:起泡分类法 • ·设例子中数组的规模为: Size = 6 算法1.2: 类模板 seqlist 的用于排序的起泡方法 template < class Type > void seqlist<Type> :: BubbleSort( ) { // 将数组p[0]到p[size-1] 逐趟进行比较,size为表的规模。 int j,k; int flag = 1; // 交换标志,flag 为1 表示出现过数据交换,继续进 //行排序。若flag为0,表示未出现过数据交换,数组 // p[0]到p[size-1]已经排好序,排序结束。 for ( j=0; j <= size - 2 && flag; j++ ){ flag = 0; for ( k = size - 1; k > j; k - -) if ( p[k-1] > p[k] ) { Type temp = p[k-1]; p[k-1] = p[k]; p[k] = temp; flag = 1; } } }

  25. 0 1 2 3 4 5 25 12 47 89 14 36 例:起泡分类法 • ·设例子中数组的规模为: Size = 6 算法1.2: 类模板 seqlist 的用于排序的起泡方法 template < class Type > void seqlist<Type> :: BubbleSort( ) { // 将数组p[0]到p[size-1] 逐趟进行比较,size为表的规模。 int j,k; int flag = 1; // 交换标志,flag 为1 表示出现过数据交换,继续进 //行排序。若flag为0,表示未出现过数据交换,数组 // p[0]到p[size-1]已经排好序,排序结束。 for ( j=0; j <= size - 2 && flag; j++ ){ flag = 0; for ( k = size - 1; k > j; k - -) if ( p[k-1] > p[k] ) { Type temp = p[k-1]; p[k-1] = p[k]; p[k] = temp; flag = 1; } } }

  26. 0 1 2 3 4 5 25 12 47 89 14 36 例:起泡分类法 • ·设例子中数组的规模为: Size = 6 算法1.2: 类模板 seqlist 的用于排序的起泡方法 template < class Type > void seqlist<Type> :: BubbleSort( ) { // 将数组p[0]到p[size-1] 逐趟进行比较,size为表的规模。 int j,k; int flag = 1; // 交换标志,flag 为1 表示出现过数据交换,继续进 //行排序。若flag为0,表示未出现过数据交换,数组 // p[0]到p[size-1]已经排好序,排序结束。 for ( j=0; j <= size - 2 && flag; j++ ){ flag = 0; for ( k = size - 1; k > j; k - -) if ( p[k-1] > p[k] ) { Type temp = p[k-1]; p[k-1] = p[k]; p[k] = temp; flag = 1; } } }

  27. 0 1 2 3 4 5 25 12 47 14 89 36 例:起泡分类法 • ·设例子中数组的规模为: Size = 6 算法1.2: 类模板 seqlist 的用于排序的起泡方法 template < class Type > void seqlist<Type> :: BubbleSort( ) { // 将数组p[0]到p[size-1] 逐趟进行比较,size为表的规模。 int j,k; int flag = 1; // 交换标志,flag 为1 表示出现过数据交换,继续进 //行排序。若flag为0,表示未出现过数据交换,数组 // p[0]到p[size-1]已经排好序,排序结束。 for ( j=0; j <= size - 2 && flag; j++ ){ flag = 0; for ( k = size - 1; k > j; k - -) if ( p[k-1] > p[k] ) { Type temp = p[k-1]; p[k-1] = p[k]; p[k] = temp; flag = 1; } } }

  28. 0 1 2 3 4 5 25 12 47 14 89 36 例:起泡分类法 • ·设例子中数组的规模为: Size = 6 算法1.2: 类模板 seqlist 的用于排序的起泡方法 template < class Type > void seqlist<Type> :: BubbleSort( ) { // 将数组p[0]到p[size-1] 逐趟进行比较,size为表的规模。 int j,k; int flag = 1; // 交换标志,flag 为1 表示出现过数据交换,继续进 //行排序。若flag为0,表示未出现过数据交换,数组 // p[0]到p[size-1]已经排好序,排序结束。 for ( j=0; j <= size - 2 && flag; j++ ){ flag = 0; for ( k = size - 1; k > j; k - -) if ( p[k-1] > p[k] ) { Type temp = p[k-1]; p[k-1] = p[k]; p[k] = temp; flag = 1; } } }

  29. 0 1 2 3 4 5 25 12 14 47 89 36 例:起泡分类法 • ·设例子中数组的规模为: Size = 6 算法1.2: 类模板 seqlist 的用于排序的起泡方法 template < class Type > void seqlist<Type> :: BubbleSort( ) { // 将数组p[0]到p[size-1] 逐趟进行比较,size为表的规模。 int j,k; int flag = 1; // 交换标志,flag 为1 表示出现过数据交换,继续进 //行排序。若flag为0,表示未出现过数据交换,数组 // p[0]到p[size-1]已经排好序,排序结束。 for ( j=0; j <= size - 2 && flag; j++ ){ flag = 0; for ( k = size - 1; k > j; k - -) if ( p[k-1] > p[k] ) { Type temp = p[k-1]; p[k-1] = p[k]; p[k] = temp; flag = 1; } } }

  30. 0 1 2 3 4 5 25 12 14 47 89 36 例:起泡分类法 • ·设例子中数组的规模为: Size = 6 算法1.2: 类模板 seqlist 的用于排序的起泡方法 template < class Type > void seqlist<Type> :: BubbleSort( ) { // 将数组p[0]到p[size-1] 逐趟进行比较,size为表的规模。 int j,k; int flag = 1; // 交换标志,flag 为1 表示出现过数据交换,继续进 //行排序。若flag为0,表示未出现过数据交换,数组 // p[0]到p[size-1]已经排好序,排序结束。 for ( j=0; j <= size - 2 && flag; j++ ){ flag = 0; for ( k = size - 1; k > j; k - -) if ( p[k-1] > p[k] ) { Type temp = p[k-1]; p[k-1] = p[k]; p[k] = temp; flag = 1; } } }

  31. 0 1 2 3 4 5 25 12 14 47 89 36 例:起泡分类法 • ·设例子中数组的规模为: Size = 6 算法1.2: 类模板 seqlist 的用于排序的起泡方法 template < class Type > void seqlist<Type> :: BubbleSort( ) { // 将数组p[0]到p[size-1] 逐趟进行比较,size为表的规模。 int j,k; int flag = 1; // 交换标志,flag 为1 表示出现过数据交换,继续进 //行排序。若flag为0,表示未出现过数据交换,数组 // p[0]到p[size-1]已经排好序,排序结束。 for ( j=0; j <= size - 2 && flag; j++ ){ flag = 0; for ( k = size - 1; k > j; k - -) if ( p[k-1] > p[k] ) { Type temp = p[k-1]; p[k-1] = p[k]; p[k] = temp; flag = 1; } } }

  32. 0 1 2 3 4 5 12 25 14 47 89 36 例:起泡分类法 • ·设例子中数组的规模为: Size = 6 算法1.2: 类模板 seqlist 的用于排序的起泡方法 template < class Type > void seqlist<Type> :: BubbleSort( ) { // 将数组p[0]到p[size-1] 逐趟进行比较,size为表的规模。 int j,k; int flag = 1; // 交换标志,flag 为1 表示出现过数据交换,继续进 //行排序。若flag为0,表示未出现过数据交换,数组 // p[0]到p[size-1]已经排好序,排序结束。 for ( j=0; j <= size - 2 && flag; j++ ){ flag = 0; for ( k = size - 1; k > j; k - -) if ( p[k-1] > p[k] ) { Type temp = p[k-1]; p[k-1] = p[k]; p[k] = temp; flag = 1; } } } 在a[6-1]和a[0]范围内最小的元素被放置在正确位置

  33. 例:最坏和最好情况下的时间复杂性 在最坏情况下的时间复杂性的分析:n为问题规模 1:交换 Swap 时间 O(1), O(1), O(1), O(1)。总和仍为O(1)。 2:IF 判断需O(1), 执行交换需O(1)。总和仍为O(1)。 3: 再加上 k - - 的时间:O(1), 总和仍为O(1)。 4:内循环所需时间为: O((n-1-j) × O(1) ) 即 O((n-1-j) 5:外循环中的循环一次还需时间 O(1): 一次赋值操作 flag = 0 O(1): 一次判断 j <= size - 2 && flag; O(1): 一次 加 1 操作 j++; 总的需要时间为: O(1) + O((n-1-j) 仍为: O((n-1-j)。 6:总的时间代价为: ∑ (n-1-j) = (n-1) + (n-2) + …… 2 + 1 = O(n2) 0 1 2 3 4 5 12 25 14 47 89 36 在a[6-1]和a[0]范围内最小的元素被放置在正确位置 a[0] 次最小 的元素 被放置 在正确 位置 a[1] 余类推 n-2 j=0 在最好情况下的时间复杂性的分析: 进行一趟检查之后,flag 为 0,已经排好序,无需再做。 故时间代价为:O(n)

  34. ·if Lim f(n)/g(n) = c; 这里 c 是常数。 f(n)、g(n) 同级别。 n->∞ • ·if Lim f(n)/g(n) = 0; f(n) 级别低。 n->∞ • ·if Lim f(n)/g(n) = ∞; g(n) 级别低。 n->∞ • 如:Lim logn/n = Lim Ln(n)loge/n • = Lim (loge/n)/1 • = Lim loge/n = 0; logn 级别低。 • 注意:这里使用了罗彼特的求极限的法则。 n->∞ n->∞ n->∞ n->∞ 时间复杂性的级别 • 注意: • 1、时间复杂性函数无时间单位。 • 2、上例采用的是均匀时间耗费。以简单语句的耗费时间为 1 。 • 3、如 if 语句,条件:O(1) + THEN OR ELSE 后的语句的时间耗费之和。 • 4、循环语句,先里后外,逐步求和。 • 5、goto 语句的分析,具体情况,具体对待。 • 时间复杂性的级别的判断:级别越低越好。

  35. 例:求 xn的程序的时间复杂性 • 方案1:直接采用循环的做法。 算法1.3: x 和 n 都是正整数,求 xn之值的简单方法 int power01( int x,int n ) { int y;y = x; // 代价 2 while( n > 1 ) // 代价 n { y *= x; n - -; } // 代价2(n-1) cout << “ x^n is ” << y << endl; // 代价 1 return y; // 代价 1 } // x 和n 都是正整数,求xn之值。 注意:根据求和定理,总的时间代价为:O(n),线形阶的。

  36. 例:求 xn的程序的时间复杂性 • 方案2:采用一些技巧,且假定不会溢出。 算法1.4: x 和 n 都是正整数,求 xn之值的时间复杂性级别低的算法 int power02( int x, int n ) { int m; m = n; int t = 1; while( m > 0 ) { m /= 2; t *= 2;} m = n; int y = 1; while( t > 1 ) { t /= 2; y *= y; if ( m >= t ) { y *=x; m -=t; } } cout << " x^n is " << y << endl; return y; } // x 和n 都是正整数,求xn之值。时间复杂性级别为O( log n ) Log n + 2 2( Log n +1) Log n + 2 Log n + 1 Log n + 1 代价 <= 3( ) Log n + 1

  37. 例:求 xn的程序的时间复杂性 算法2的工作原理,可用求 x55来加以说明: x55= x110111 = x32+16+0+4+2+1来加以说明。 程序的 第一个 while 求出 >= 55 的最小的2的正整数幂 64,64/2 可得到32,在程 序的 第二个 while 中用到它。在程 序的 第二个 while 中: 55 - 32 = 23 得到 x110111 中的 幂指数中的最左位的1 23 - 16 = 7 得到 x110111 中的 幂指数中的左起第二位的1 7 - 8 < 0 得到 x110111 中的 幂指数中的左起第三位的0 7 - 4 = 3 得到 x110111 中的 幂指数中的左起第4位的1 3 - 2 = 1 得到 x110111 中的 幂指数中的左起第5位的1 1 - 1 =0 得到 x110111 中的 幂指数中的左起第 6三位的1 知道了上述求法之后,求 x110111 就很方便了: 先求 x1 ,1 * x=》y 再求 x11 , x11= x10 * x1 = x10 * x1 =》y * y * x =》y 再求 x110 , x110= x11 * x11 =》 y * y 其余,依次类推。

  38. 有效算法的重要性 • ·计算机不是万能的,并非所有的算法计算机都能够计算出有用的结果。差的算法不一 定有实际意义。 • 举一个例子加以说明。假定时间复杂性函数的时间单位为 us 函数 n=20 n=50 n=100 n=500 1000n .02s .05s .15s .5s 1000nlogn .09s .3s .6s 4.5s 100n2 .04s .25s 1s 25s 10n3 .02s 1s 10s 21分 nlogn .4s 1.1小时 220天 5× 108世纪 2n/3 .0001s 0.1s 2.7小时 5× 108世纪 2n 1s 35年 3× 104世纪 3n 58分 2×109世纪 易性算法 顽性算法

  39. 有效算法的重要性 • ·硬件速度的提高和问题的求解规模之间的关系:硬件速度提高 10 倍,并不意味着求解问题 的规模同样提高 10 倍。由于算法不同,差别很大。设时间复杂性函数的时间单位为ms。 提速之前 在 1 秒内 在 1 分钟内在 1 小时 A1:n 1000 6 * 104 3.6 * 106 A2:nlogn 140 4893 2 * 105 A3: n2 31 244 1897 A4: n3 10 39 153 A5: 2n 9 15 21 例如:设 1 分钟内算法 A5的求解规模为 s5: 则:2s5 = 60 * 103 (ms) 解之:s5 = 15

  40. 例如:设提速 10 倍后在时间 t 秒内,A5 的求解规模为 z5: t * 1000 t * 1000*10 解之:z5 = s5 +3.3 2s5 = 2z5 有效算法的重要性 • ·硬件速度的提高和问题的求解规模之间的关系:硬件速度提高 10 倍,并不意味着求解问题 的规模同样提高 10 倍。由于算法不同,差别很大。设时间复杂性函数的时间单位为ms。 提速10倍后 提速10倍前求解规模 提速10倍后求解规模 A1:n s1 10s1 A2:nlogn s2 10s2 A4: n2 s4 3.16s3 A3:n3 s3 2.15s4 A5: 2n s5 s5+3.3

  41. 大 Ω 表示法: • ·定义;如果存在着正的常数 c 和自然数 n0,当 n >= n0时;有 f (n) >= Cg(n) 成立,则 称 f( n ) = Ω (g( n )) 。 • 大Θ 表示法: • ·定义;如果存在着正的常数 c1、c2 和自然数 n0,当 n >= n0时;有 • C1 × g(n) <= f (n) <= C2 ×g(n) 成立,则称 f( n ) = Θ (g( n )) 。 • ·例、 设 T(n) = (n+1)2 = Θ ( n2) • 小 o 符号: • ·定义;f(n) = o(g( n )) 当且仅当 f(n) = O(g( n )) 且 f(n) != Ω (g( n )) • ·例、 设 T(n) = 3n+1 = O ( n2) 且 3n+1 != Ω( n2) 。所以, 3n+1 = o ( n2) • 但 T(n) = 3n+1 != o ( n ) 其它表示法 • ·例、 设 T(n) = (n+1)2 • = n2+2n2 +1 >= n2 ; 在 n 为任何数时,所以,T(n) = Ω (n2)

More Related