数据结构
通常意义上,我们将数据结构分为逻辑结构和存储结构。
逻辑结构
- 集合结构
集合结构中的数据元素除了同属于一个集合外无其他关系。 - 线性结构
线性结构中数据元素之间是一对一的关系。 - 树结构
树结构中的数据元素之间存在一种一对多的层次关系。 - 图结构
图结构的数据元素是多对多的关系
几种逻辑结构层次图:
存储结构
即如何把数据元素存储到计算机的存储器中
- 顺序存储结构(线型或其他)
是把数据元素存放在一组连续的地址空间中,其数据间的逻辑关系和存储关系相一致。
- 链式存取结构(树、图结构)
是把数据元素存放在任意的存储单元里,可连续可不连续。用一个指针存放数据元素的地址,从而查找数据元素位置。
抽象数据类型(ADT)
是指一组性质相同的值得集合及定义在此集合上的一些操作的总称。
抽象:是指取出事物具有的普遍性的本质。它要求抽出问题的特征而忽略非本质的细节,是对具体事物的一个概括。
例如很多编程语言的整型,浮点型,字符型这些,指的就是数据类型。
在C语言中,按取值的不同,数据类型可以分为两类:
- 原子类型:不可以再分解的基本类型,例如整型、浮点型、字符型等。
- 结构类型:由若干个类型组合而成,是可以再分解的,例如整型数组是由若干整型数据组成的。
ADT的标准格式:
ADT 抽象数据名
Data
数据元素之间逻辑关系的定义
Operation
操作
endADT
算法和算法分析
算法的特性
1)有穷性。即每一步必须在又穷时间内完成。
2)确定性。无二义性。
3)可行性。程序可通过基本操作运算执行有限次来实现。
4)输入。输入通常用形参表示,被调用时从主函数输入值。
5)输出。无输出的算法没有意义。
一个算法可以有零个或多个输入,也可以有一个或多个输出。
算法的时间复杂度
设计算法要尽量提高效率,这里的算法即是指算法的执行时间。
那么如何度量一个算法的执行时间呢?
这就引出了算法时间复杂度的概念
算法的时间复杂度取决于问题的规模和待处理数据的状态。
影响算法时间代价的最主要因素是问题规模。
问题规模一般用整数n表示,对于不同的问题n的含义不同。
- 在排序运算中n为参加排序的记录数
- 在矩阵运算中n为矩阵的阶数
- 在多项式运算中n为多项式的项数
- 在集合运算中n为集合中元素的个数
- 在树的有关运算中n为树的结点个数
- 在图的有关运算中n为图的定点数或边树。
显然,n越大算法的执行时间越长.
牢记以上n所代表的意义,对接下来计算时间复杂度有很大的帮助。
那么现在我们来看一个例子初步理解算法时间复杂度的运算
//第一种算法
int sum=0,n=100;//执行1次
for(int i=0;i<n;i++)//执行n+1次
{
sum+=i;//执行n次
}
//第二种算法
int sum=0,n=100;//执行1 次
sum=n*(n+1)/2;//执行1 次
综上我们得:
第一种算法执行了1+(n+1)+n=2n+2次
第二种算法执行了1+1=2次
如果我们把循环看做一个整体,忽略头尾判断的开销,俺么这两个算法就是n和1的差距
此时你可能还不太理解,为什么可以2n+2和2变成了n和1,不要着急,看下面的例子。
int s=0,n=100,x=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
x++;
s+=s;
}
}
此时,算法包含两个for循环嵌套,外层执行100次,那么内层循环则执行1002次则该算法执行次数为1+n+n2+n2+n2=3n2+n+1。
由函数的渐进增长我们忽略头和尾那么得到该算法的时间复杂度为n2。
同理对于三阶算法:T(n)=O(n3)
在这里我们展现了时间复杂度的表示方法。
算法的时间复杂度:
T(n)=O(f(n)),
其中f(n)是问题规模n的某个函数。
表示随问题规模n的增大,算法的执行时间增长率和f(n)的增长率相同。通俗讲就是(执行次数=时间)。
注意公式中T和O都为大写,O()成为大O记法。
计算时间复杂度攻略:
- 用常数1代替运行次数中的加法常数。
- 在修改后的运行次数函数中,只保留最高阶项。
- 如果最高阶数不是1,则去除这个项相乘的常数。
将算法分为
1、常数阶 T(n)=O(1)
2、线性阶:一般为非嵌套循环 T(n)=O(n)
3、平方阶:嵌套(内外层循环)T(n)=O(n2)
4、立方阶:三层嵌套 T(n)=O(n3)
5、nlogn阶:O(nlogn)
6、指数阶:O(2n)
7、对数阶:看以下例子
int i=1;
while(i<=n)
{
i=i*3;
}
分析该程序可知,每次i*3之后,就距离n更近一步,设有x个3相乘后的结果大于n,则退出循环。
此时得到:
3x = n ——>x=log3n因此得到该算法的时间复杂度为O(log3n)。
常用的时间复杂度所耗费的时间从小到大依次是:
O(1) < O(logn) < O(n) < O(nlogn) < O(n2) < O(n3) < O(2n) < O(n!) < O(nn)
轻松做题务必牢记以上!!!
对于算法时间复杂度的度量分为最好时间复杂度,最坏时间复杂度以及平均时间复杂度
注:严蔚敏c语言版的数据结构中。只讨论最坏情况下的时间复杂度,即分析在最坏情况下,算法执行的上界。