一、时间复杂度
计算机科学中,算法的时间复杂度是一个函数,它定性描述了该算法的运行时间。时间复杂度常用大O符号表述,不包括这个函数的低阶项和首项系数。使用这种方式时,时间复杂度可被称为是渐近的,它考察当输入值大小趋近无穷时的情况。
定义:如果存在正常数c和m,使得当N >= m时,T(N)<=cf(N),则记为T(N)=O(f(N))。
二、时间复杂度的一些运算法则
-
法则1:
如果T1(N) = O(f(N)), T2(N) = O(g(N)),那么 (a) T1(N) + T2(N) = max(O(f(N)), O(g(N)))
(b) T1(N) * T2(N) = O(f(N)) * O(g(N)) -
法则2:
对于任意常数k,(logN)^k = O(N) ——》对数增长得非常缓慢!
三、程序运行时间的估算
int Sum(int N)
{
int i, S = 0, //1
for ( i=1;i<=N;i++) //2
S += i*i*I; //3
return S; //4
}
声明不计时间。
主体程序的第1行和第4行各占一个时间单元。
第2行初始化占1个时间单元,测试i<=N 共花费N+1个时间单元,自增运算N个时间单元。
第3行每次执行占用4个时间单元,共4N个。
所以总共是6N + 4,我们说该函数是O(N)
1、一般法则
- 法则1——for循环
一次for循环的运行时间至多是该for循环内语句(包括测试)的运行时间乘以迭代次数
- 法则2——嵌套for循环
由里向外分析。总时间为每个for循环运行时间的乘积
- 法则3——顺序语句
将各个语句的运行时间求和即可
- 法则4——if/else语句
对于程序片段
if(…)
s1
else
s2
四、数据结构中的一些概念
- 表
“表”定义为列的集合。与电子表格相似,数据在表中是按行列格式组织排列的。表中的每一列都设计为存储某种类型的信息(例如日期、名称、美元金额或数字)。表上有几种控制(约束、规则、默认值和自定义用户数据类型)用于确保数据的有效性。
“表”的实现形式多种多样,常用的方法有数组、指针。
表有很多种类型,例如顺序表、链表等等。
这次培训主要介绍两种特殊的“表”——“栈”和“队列”
- 栈
定义:栈(stack)又名堆栈,它是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈(PUSH)或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈(POP)或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
“栈”是计算机中的重要概念。在计算机系统中,栈可以是一个储存数据的动态内存区域,程序可以将数据压入栈中,也可以将数据从栈顶弹出。在程序的运行中,栈保存了一个函数调用时所需要的维护信息,这常常称之为堆栈帧或者活动记录。
重要性质:后进先出(LIFO)
栈的工作过程
- 队列
定义:队列(queue)是一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。队列中没有元素时,称为空队列。
队列的应用非常广泛,比如在图的广度优先遍历中。队列作为一种最基本的数据结构——限制性的线性表,实现方法和其它类型的表没有两样,同样可以用数组和指针模拟。
当然用线性表也可以实现队列的所有功能,但正是由于栈和队列太常用,才单独抽象成一种数据结构。
重要性质:先进先出(FIFO)
队列的工作过程
对于很大量的输入数据,表的线性访问时间太慢,不宜使用,
还有一种简单的数据结构,其大部分操作的运行时间平均为O(logN),
它的名字叫做树(tree)。
- 树
树是一种数据结构,它是由n(n>=1)个有限结点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。
它具有以下的特点:
每个结点有零个或多个子结点;
没有父结点的结点称为根结点;
每一个非根结点有且只有一个父结点;
除了根结点外,每个子结点可以分为多个不相交的子树。
树
树也可以这样定义:树是由根结点和若干颗子树构成的。
树是由一个集合以及在该集合上定义的一种关系构成的。集合中的元素称为树的结点,所定义的关系称为父子关系。
父子关系在树的结点之间建立了一个层次结构。在这种层次结构中有一个结点具有特殊的地位,这个结点称为该树的根结点,或称为树根。
这种性质使得递归成为了对“树”处理的常用方法。
实例一:二分查找
分析一下这个算法的时间复杂度
二分查找
{
int left,right;
int mid;
left=start;
right=end;
while(left<=right)
{
mid=left+(right-left)/2;//还是溢出问题
if(key==Array[mid]) return mid;
else if(key<Array[mid]) right=mid-1;
else if(key>Array[mid]) left=mid+1;
}
return -1;
}
实例二:对简单递归法实现斐波那契数列的分析
long int Fib(int N)
{
if(N <= 1)
return 1;
else
return Fib(N - 1) + Fib(N - 2)
}