数据结构算法分析怎么写_数据结构和算法分析
问题引出
假设有⼀道题⽬:有⼀组N个数⽽要确定其中第k个最⼤者,我们称之为选择问题,那么这个程序如何编写?最直观地,⾄少有两种思路:
1、将N个数读⼊⼀个数组中,再通过某种简单的算法,⽐如冒泡排序法,以递减顺序将数组排序,则第k个位置上的元素就是我们需要的元素
2、稍微好⼀些的做法,将k个元素读⼊数组并以递减顺序排序,接着将接下来的元素再逐个读⼊,当新元素被读到时,如果它⼩于数组中的第k个元素则忽略之,否则将其放到数组中正确的位置上,同时将数组中的⼀个元素挤出数组,当算法终⽌时,位于第k个位置上的元素作为答案返回
这两种算法都很简单,但是假设我们有⼀千万个元素的随机⽂件和k=5000000进⾏模拟将发现,两个算法尽管最终都可以给出正确答案,但是在合理时间内均⽆法结束。因此,这两种算法都不能被认为是好的算法,因为从实际⾓度出发,它们⽆法在合理的时间内处理输⼊的数据。
数据结构和算法分析的提出
在许多问题中,⼀个很重要的观念是:写出⼀个⼯作程序并不够。如果这个程序在巨⼤的数据集上运⾏,那么运⾏时间就变成了重要的问题,我们将在接下来的⽂章中看到对于⼤量的输⼊如何估计程序的运⾏时间,尤其是如何在未具体编码的情况下⽐较两个程序运⾏的时间。我们还将看到彻底改进程序速度以及确定程序瓶颈的⽅法,这些⽅法将使得我们能够发现需要我们集中精⼒努⼒优化的那些代码段。
那么,⾸先,先了解⼀下什么是数据结构和算法分析(特别指出,后⽂的例⼦均以Java代码编写)。
数据结构
数据结构是计算机存储、组织数据的⽅式,是指数据相互之间存在⼀种或多种特定关系的数据元素的集合。通常情况下,精⼼选择的数据结构可以带来更⾼的运⾏或者存储效率(这就是为什么我们要研究数据结构的原因),数据结构往往同⾼效的检索算法和索引技术相关。
常见的数据结构有数组、栈、队列、链表、树、散列等,这些数据结构将是本数据结构的分类中重点研究的对象。
算法分析
算法是为求解⼀个问题需要遵循的、被清楚指定的简单指令的集合。对于⼀个问题,⼀旦某种算法给
定并且(以某种⽅式)被确定是正确的,那么重要的异步就是确定该算法将需要多少注⼊时间或空间等资源量的问题。如果:
1、⼀个问题的求解算法竟然需要长达⼀年时间,那么这种算法就很难有什么⽤处
2、⼀个问题需要若⼲个GB的内存的算法,在当前⼤多数机器上也是⽆法使⽤的
数学基础
⽆论是数据结构还是算法分析,都⽤到了⼤量的数学基础,下⾯将这些数学的基础简单总结⼀下:
1、指数
(1)X A X B = X A+B
梦见耳朵出血(2)X A/X B = X A-B
(3)(X A)B = X ABsi
(4)X N + X N = 2X N ≠ X2N
(5)2N + 2N = 2N + 1
2、对数
(1)X A = B当且仅当log x B = A
(2)log A B = log C B / log C A
(3)logAB = logA + logB,A>0且B>0
3、级数
(1)∑2i = 2N+1 - 1
(2)∑A i = (A N+1 - 1) / (A - 1),若0i ≤ 1 / (1 - A)
金鸡百花手机影片4、模运算
如果N整除A、N整除B,那么就说A与B模N同余,记为A≡B(mod N)。直观地看,这意味着⽆论是A还是B被N去除,所得余数都是相同的,于是假如有A≡B(mod N),则:
(1)A + C ≡ B + C(mod N)
(2)AD ≡ BD (mod N)
时间复杂度
在计算机科学中,算法的时间复杂度是⼀个函数,它定量描述了该算法的运⾏时间。这是⼀个关于代表算法输⼊值的字符串的长度的函数,时间复杂度常⽤⼤O符号表述,不包括这个函数的低阶项和⾸项系数,使⽤这种⽅式时,时间复杂度可被称为是渐进的,他考察当输⼊值⼤⼩趋近⽆穷时的情况。
那么⾸先先看⼀个简单的例⼦,这⾥是计算Σi3的⼀个简单程序⽚段:
1 public static void main(String[] args)
2 {
3 System.out.println(sum(5));
4 }
5
不论不论都可以造什么句子6 public static int sum(int n)
7 {
8 int partialSum;
9 10 partialSum = 0;11 for (对这个程序⽚段的分析是简单的:
1、声明不记⼊时间
2、第10⾏和都14⾏各占⼀个时间单元
3、第12⾏每次执⾏占⽤4个时间单元(两次乘法、⼀次加法和⼀次赋值),⽽执⾏N次共占⽤4N个时间单元
4、第11⾏在初始化i,测试i≤n和对i的⾃增都隐含着开销,所有这些总开销是初始化1个时间单元,所有的测试为N+1个时间单元,所有⾃增为N个时间单元,共2N+2个时间单元
忽略调⽤⽅法和返回值的开销,得到总量是6N+4个时间单元,按照最开始的定义不包括这个函数的低阶项和⾸项系数,因此我们说该⽅法的时间复杂度是O(N)。继⽽,我们顺便得出若⼲个⼀般法则:
法则⼀----for循环
⼀个for循环的运⾏时间⾄多是该for循环内部那些语句(包括测试)的运⾏时间乘以迭代的次数,因此假如⼀个for循环迭代N次,那么其时间复杂度应该为O(N)
法则⼆----嵌套for循环
从⾥向外分析这些循环,在⼀组嵌套循环内部的⼀条语句总的运⾏时间为该语句的运⾏时间乘以该组所有的for循环的⼤⼩的乘积,因此假
如有以下代码:
1 public static int mutliSum(int n)
2 {
3 int k = 0;
4 for (int i = 0; i < n; i++)
5 {
6 for (int j = 0; j < n; j++)
7 {
8 k++;
9 }10 }11 12 return k;13 }
则其时间复杂度应为O(N2)
法则三----顺序语句
将各个语句的运⾏时间求和即可,⽐如有以下代码:
1 public static int sum(int n)
2 {
3 int k = 0;
4
5 for (int i = 0; i < n; i++)
6 k++;
7 for (int i = 0; i < n; i++)
做梦梦见掉头发
8 {
9 for (int j = 0; j < n; j++)10 {11 k++;12 }13 }14 15
第⼀个for循环的时间复杂度为N,第⼆个嵌套for循环的时间复杂度为N2,综合起来看sum⽅法的时间复杂度为O(N2)
常见的时间复杂度与时间效率的关系有如下的经验规则:
dnf武器图片O(1) < O(log2N) < O(N) < O(N * log2N) < O(N2) < O(N3) < O(N!)宽带连接 自动连接
⾄于每种时间复杂度对应哪种数据结构和算法,后⾯都会讲到,从上⾯的经验规则来看:前四个算法效率⽐较⾼,中间两个差强⼈意,最后⼀个⽐较差(只要n⽐较⼤,这个算法就动不了了)。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论