数据结构 算法

两种算法的比较

1+2+3…………+100

int i,sum = 0,n = 100;
for(i = 1;i <= n ;i++)
{
    sum = sum + i;
}
 printf("%d",sum);

高斯求和(求等差数列的和的算法)

int sum = 0,n = 100;
sum = (1 + n) *n / 2;
printf("%d",sum)

算法定义

算法是解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每一条指令表示一个或多个操作。

算法的特性

输入、输出、有穷性、确定性和可行性。

输入输出

算法具有零个或多个输入。

算法至少有一个或多个输出。

有穷性

指算法在执行有限的步骤之后,自动结束而不会出现无限循环,并且每一个步骤在可接受的时间内完成。

确定性

算法的每一步骤都具有确定的含义,不会出现二义性。

可行性

算法的每一步骤都必须是可行的,也就是说,每一步都能够通过执行有限次数完成。

算法设计的要求

正确性

算法的正确性是指算法至少应该具有输入输出和加工处理无歧义性,能正确反映问题的需求,能够得到问题的正确答案。

大体分为一下四个层次:

(1)算法程序没有语法错误。

(2)算法程序对于合法的输入数据能够产生满足要求的输出结果。

(3)算法程序对于非法的输入数据能够得出满足规格说明的结果。

(4)算法程序对于精心选择的,甚至刁难的测试数据都有满足要求的输出结果。

一般使用第3层次作为程序正确的标准。

可读性

算法设计的另一目的是为了便于阅读、理解和交流。

健壮性

当输入数据不合法时,算法也能做出相关处理,而不是产生异常或莫名其妙的结果。

时间效率高和存储量低

设计算法应尽量满足时间效率高和存储量低的需求。

算法效率的度量方法

事后统计方法

主要是通过设计好的测试程序和数据,利用计算机计时器对不同算法编制的程序的运行时间进行比较,从而确定算法效率的高低。

缺陷:

1.必须依据算法事先编制好程序

2.时间的比较依赖计算机硬件和软件等环境因素

3.算法的测试数据设计困难,且程序的运行时间往往还与测试数据的规模有很大关系(效率很高的算法在小的测试数据面前往往得不到体现)

事前分析估算方法

在计算机程序编制前,依据统计方法对算法进行估算。

影响时间的因素:

(1)算法采用的策略、方法(算法好坏的根本)

(2)编译产生的代码质量(由软件支持)

(3)问题的输入规模

(4)机器执行指令的速度(取决于硬件的性能)

一个程序的运行时间,依赖于算法的好坏和问题的输入规模。

第一种算法:

int i, sum = 0, n = 100;	/* 执行1次 */
for(i = 1; i <= n; i++)	/* 执行了n+1次 */
{
	sum = sum + i;			/* 执行n次 */
}
printf("%d", sum);			/* 执行1次 */

执行了2n+3次

第二种算法:

int sum = 0,n = 100;		/* 执行一次 */
sum = (1 + n) * n / 2;		/* 执行一次 */
printf("%d", sum);			/* 执行一次 */

执行了3次

延伸算法

int i, j, x = 0, sum = 0, n = 100;	/* 执行一次 */
for(i = 1; i <= n; i++)
{
	for (j = 1; j <= n; j++)
	{
		x++;						/* 执行n×n次 */
		sum = sum + x;
	}
}
printf("%d", sum);					/* 执行一次 */

执行n^2{}

在分析程序运行时间时,最重要的是把程序看成是独立于程序设计语言的算法或一系列步骤。

函数的渐进增长

给定两个函数f(n)和g(n),如果存在一个整数N,使得对于所有的n>N,f(n)总是比g(n)大,那么,我们说f(n)的增长渐进快于g(n)。

判断一个算法的效率时,函数中的常数和其他次要项常常可以忽略,而更应该关注主项(最高阶项)的阶数。

算法时间复杂度

算法时间复杂度的定义

语句总的执行次数是关于问题规模的函数,进而分析执行次数随问题规模变化情况确定其数量级。算法执行时间的增长率和执行次数的增长率相同,称作算法的渐进时间复杂度,简称时间复杂度。(一般情况下,随问题规模变大时,执行次数增长最慢的算法为最优算法)

推导大O阶方法

用常数1取代运行时间中的所有加法常数

在修改后的运行次数函数中,只保留最高阶项

如果最高阶存在且其系数不是1,则去除与这个项目相乘的系数,得到的结果就是大O阶。

常数阶

int sum = 0, n = 100;		/* 执行1次 */
sum = (1+n)*n/2;			/* 执行第1次 */
sum = (1+n)*n/2;			/* 执行第2次 */
sum = (1+n)*n/2;			/* 执行第3次 */
sum = (1+n)*n/2;			/* 执行第4次 */
sum = (1+n)*n/2;			/* 执行第5次 */
sum = (1+n)*n/2;			/* 执行第6次 */
sum = (1+n)*n/2;			/* 执行第7次 */
sum = (1+n)*n/2;			/* 执行第8次 */
sum = (1+n)*n/2;			/* 执行第9次 */
sum = (1+n)*n/2;			/* 执行第10次 */
printf("%d",sum);		    /* 执行1次 */

不管常数是多少,都记作O(1)

线性阶

int i;
for(i = 0; i < n; i++)
{
	/* 时间复杂度为O(1)的程序步骤序列 */
}

时间复杂度为O(n)

对数阶

int count = 1;
while count < n)
{
	count = count * 2;
	/* 时间复杂度为O(1)的程序步骤序列 */
}

时间复杂度为O(\log n

平方阶

int i,j;
for(i = 0; i < n; i++)
{
	for(j = 0; j < n; j++)                       
	{                                      
		/* 时间复杂度为O(1)的程序步骤序列 */
	}                                      
}

int i,j;
for(i = 0; i < m; i++)
{
	for(j = 0; j < n; j++)                
	{                                      
		/* 时间复杂度为O(1)的程序步骤序列 */
	}                                      
}
int i,j;
for(i = 0; i < n; i++)
{
	for(j = i; j < n; j++)  /* 注意j = i而不是0 */
	{                                      
		/* 时间复杂度为O(1)的程序步骤序列 */
	}                                      
}

时间复杂度为O(n^{2}

常见的时间复杂度

非正式术语
O(1)常数阶
O(n)线性阶
O(n^{2})平方阶
O(\log n)对数阶
O( n\log n)n\log n
O(n^{3})立方阶
O(2^{n})指数阶

 最坏情况与平均情况

平均运行时间是所有情况中最有意义的,因为它是期望的运行时间。

一般在没有特殊说明的情况下,都是指最坏时间复杂度。

算法空间复杂度

算法所需的存储空间

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值