●算法(Algorithm)
1.一个有限指令集
2.接受一些输入(有些情况下不需要输入)
3.产生输出
4.一定在有限步骤之后终止
5.每一条指令必须
1)有充分明确的目标,不可以有歧义
2)计算机能处理的范围之内
3)描述应不依赖于任何一种计算机语言以及具体的实现手段
算法的五个基本特征
①输入
输入的参数,个数(>=0),例如:直接打印,就无参数传入。
②输出
输出和返回值,个数(>0),必须要有输出,至少要有个打印。
③有穷性
有限的执行步骤之后,不会出现无限循环,在有限时间内完成。
④确定性
每一步都必须具有具体的含义,不会出现二义性。
⑤可行性
刚才讲了要在有限时间内完成,即每一步是可行的,每一步都是有限时间的。
算法设计的要求
①正确性
②可读性:便于程序员之间阅读,理解,交流,有助于人们理解算法,易修改调试。
③健壮性:对输入数据(参数)进行合法性校验。当输入数据不合法时,算法也会进行相关的处理,而不是出现异常。
④尽量满足时间效率高和存储量低的需求(时间复杂度和空间复杂度低)
●复杂度
空间复杂度S(n)
根据算法写成的程序在执行时占用存储单元的长度。这个长度往往与输入数据的规模有关。空间复杂度过高的算法可能导致使用的内存超限,造成程序非正常中断。
时间复杂度T(n)
根据算法写成的程序在执行时耗费时间的长度。这个长度往往也与输入数据的规模有关。时间复杂度过高的低效算法可能导致我们在有生之年都等不到运行结果。
T(n) = O(f(n))
常数阶:O(1)(单纯的分支结构也是执行一次)
if(....)
{
printf("....");
} /* 执行一次 */
else
{
printf("....");
}
线性阶:O(n)(循环结构)
for (i = 0; i < n; i++)
{
/* 执行n次 */
........;
}
对数阶:O(log n)(迭代)
while (count < n)
{
//2^x=n x=logn
count = count * 2;
.....;
}
平方(次方)阶:O(n^2) , O(n^3)…
for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
{
......;
}
}
指数阶:O(2^n)…
等等…
复杂度分析小窍门
◆若两段算法分别有复杂度T1(n) = O(f1(n)) 和T2(n) =O(f2(n)),则
① T1(n) + T2(n) = max( O(f1(n)), O(f2(n)) )
② T1(n) T2(n) = O( f1(n) f2(n) )
◆一个for循环的时间复杂度等于循环次数乘以循环体代码的复杂度
◆if-else 结构的复杂度取决于if的条件判断复杂度和两个分枝部分的复杂度,总体复杂度取三者中最大
●所以到底什么是数据结构??
数据对象在计算机中的组织方式
逻辑结构
物理存储结构
数据对象必定与一系列加在其上的操作相关联
完成这些操作所用的方法就是算法
①逻辑结构:
数据的逻辑结构,简单地理解,就是指的数据之间的逻辑关系。
数据之间的逻辑关系可简单的分为三类:
▲一对一 (线性结构,串)
▲一对多 (层次结构 树)
▲多对多 (图)
②物理结构
指的是数据在计算机存储器中的存放方式(例如:内存中),可以选择集中存放,还是分散存放。
具体表现:顺序存储(地址连续)和链式存储(指针表示逻辑关系)。
●应用实例:最大子列和问题
①
// T ( N ) = O ( N^3 )
//算法一 最复杂
int MaxSubseqSum1( int A[], int N )
{
int ThisSum, MaxSum = 0;
int i, j, k;
for( i = 0; i < N; i++ )
{
/* i是子列左端位置*/
for( j = i; j < N; j++ )
{
/* j是子列右端位置*/
ThisSum = 0; /* ThisSum是从A[i]到A[j]的子列和*/
for( k = i; k <= j; k++ )
{
ThisSum += A[k];
}
if( ThisSum > MaxSum ) /* 如果刚得到的这个子列和更大*/
{
MaxSum = ThisSum; /* 则更新结果*/
}
} /* j循环结束*/
} /* i循环结束*/
return MaxSum;
}
②
// T ( N ) = O ( N^2 )
//算法二 也复杂
int MaxSubseqSum2(int A[], int N)
{
int ThisSum, MaxSum = 0;
int i, j;
for (i = 0; i < N; i++)
{ /* i是子列左端位置*/
ThisSum = 0; /* ThisSum是从A[i]到A[j]的子列和*/
for (j = i; j < N; j++)
{ /* j是子列右端位置*/
ThisSum += A[j];
/*对于相同的i,不同的j,只要在j-1次循环的基础上累加1项即可*/
if (ThisSum > MaxSum) /* 如果刚得到的这个子列和更大*/
{
MaxSum = ThisSum; /* 则更新结果*/
}
} /* j循环结束*/
} /* i循环结束*/
return MaxSum;
}
③
// T ( N ) = O( N log N )
//算法三:分而治之 复杂度较低 代码实现较难
④
// T( N ) = O( N)
//算法四 复杂度最低
//每输入一个数据就进行即时处理,在任何一个地方中止输入,算法都能正确给出当前的解。
int MaxSubseqSum4(int A[], int N)
{
int ThisSum, MaxSum;
int i;
ThisSum = MaxSum = 0;
for (i = 0; i < N; i++)
{
ThisSum += A[i]; /* 向右累加*/
if (ThisSum > MaxSum)
{
MaxSum = ThisSum; /* 发现更大和则更新当前结果*/
}
else if (ThisSum < 0) /* 如果当前子列和为负*/
{
ThisSum = 0; /* 则不可能使后面的部分和增大,抛弃之*/
}
}
return MaxSum;
}
运行时间比较
NA表示已经无法运算了