(一)实例分析
要研究一个程序的运行效率和哪些因素有关,首先我们看这几个实例
例:Printn函数:递归实现和循环实现
#include<stdio.h>
#include<math.h>
void printn(int n);
void printm(int n);
int main()
{
int n;
scanf("%d",&n);
printf("%d",printn(n));
}
void printn(int n)
{
int i=1;
for(i=1;i<n;i++)
{
printf("%d ",i);
}
}
void printm(int n)
{
if(n!=0)
{
printm(n-1);
printf("%d",n);
}
}
我们可以发现,程序不喜欢跑递归,因为它对程序的占有量很大。非正常的递归由于空间不够用)程序对空间的使用( 解决问题方法的效率和空间的利用效率有关)
例:计算多项式的值
#include<stdio.h>
#include<time.h>
#include<math.h>
#define max 1e7
int clockt,start,stop;//(*clock_t是函数返回的变量类型)
double duration;//(记录函数运行的时间,秒为单位)
int main()
{
int n;
scanf("%d",&n);
double a[100];
int i,j;
for(i=0;i<n;i++)
{
a[i]=i;
}
start=clock();
for(j=0;i<max;j++)
f1(n,a,1.1);
stop=clock();
duration=((double)(stop-start)/CLK_TCK)/max;
printf("%lf",duration);
}
double f1(double n,int a[],double x)
{
int p=a[0],i=0;
for(i=1;i<=n;i++)
{
p+=a[i]*pow(x,i);
}
return p;
} //f(x)=a0+a1x+a2x^2+...anx^n;
//秦九韶算法 f(x)=a0+x(a1+x(a2+x(a3(...a n-1+x(an))))
double f2(int n,double a[],double x)
{ int i=0,m;
double p=a[n];
for(i=n;i>0;i--)
{
m+=x*p+a[i-1];
}
return m;
}
这里我们引入一种对数器,来看一种算法是否高效。
方法1:好方法 方法2:坏方法
随机样本产生器
rest1 != 或者== rest2
(Tn1=(n^2+n)/2 Tn2= n)
打点记录时间:clock()捕捉程序从运行到clock()被调用经历的时间。即为时钟打 点单位 clock tick;
常数CLK-TCK 机器时钟每秒所走的时钟打点数
函数跑的太快,可以让它多跑几次,可以让它被捕捉到
求1到100的数字之和
double sum(double n)
{
double sum1=(n+1)*n/2;
return sum1;
}
求最大子列和
int maxsum1(int a[],int n)
{
int thissum,maxsum=0;
int i,j,k;
for(i=0;i<n;i++) /*i为子列左端 ,j为右端)
for(j=i;j<n;j++)
thissum=0;/*thissum为a[i]到a[j]的子列和 */
for(k=i;k<=j;k++)
thissum+=a[j];
if(thissum>maxsum)
maxsum=thissum;
return maxsum; t(n)=n^3;
}
int maxsum2(int a[],int n)
{
int thissum,maxsum=0;
int i,j,k;
for(i=0;i<n;i++)
thissum=0
for(j=i;j<n;j++)//i为子列左端 ,j为右端
thissum+=a[j];//对于相同i不同的j只需要在前一次的循环上累加一项即可
thissum+=a[j];
if(thissum>maxsum)
maxsum=thissum;
return maxsum; t(n)=n^2;
}
int maxsum4(int a[],int n)
{
int thissum=0,maxsum=0,i;
for(i=0;i<n;i++)
thissum+=a[i];
if(thissum>Maxsum)
{
maxsum=thissum;
}
else if(thissum<0)
{
thissum=0;
}//如果子列和为负数,则不可能使得后面的部分越加越大,不如舍去
return maxsum;
}
以上我们引入四种算法,可见优劣。接下来我们将系统走入数据结构和算法。
(二)数据结构
数据结构是数据对象在计算机的组织形式
1.逻辑结构
线性结构(一对一)
树(先分为一类一类,每类里面还有好多。一对多)
图(多对多的关系网)
2.物理存储结构
逻辑结构在内存中怎么放 连续着放或者东一个西一个隔开放置即这个是用数组还是用链表存放
3.描述数据结构的方法:抽象(不具体即不依赖具体机器和数据存储结构和编程语言都无关)
数据对象必定与一系列加在其上的操作相关联
完成这些操作的所用方法就是算法
4.数据类型(abstract date type)
数据类型包含:数据对象集和数据集合相关联的操作集。
(三)算法
1、算法是一个有限的指令集,接受一些输入,产生输出 ,一定在有限步骤结束后终止。 每一条指令必须(有充分明确的目标而不能产生歧义 在计算机能处理的范围之内 描述应该不依赖于任何一种计算机语言以及它的具体实现过程)
2.算法的好坏
空间复杂度S(n)==C*n------根据算法写成的程序在执行时占用存储单元的长度。长度往往与输入数据的规模有关。(与数据的规模相关)。 时间复杂度T(n)根据算法写成的程序耗费的时间长度(与数据规模相关)
3.什么是好的算法 平均复杂度<=最坏复杂度
Tavg(n)<=Twor(n)
4. 复杂度的渐进:T(n)=O(f(n))表示存在常数C>0,N>0时使得n>=N有T(n)<=c*f(n) ;T(n)>=C*g(n) (Tn=Ω(g(n)) T(n)=O(h(n)):同时有O(n)和Ω(n)
5.( 1)俩段时间复杂度T1和T2 T1+T2=max(T1,T2)
T1*T2=O(f1*f2)
(2)若Tn是关于n的k阶多项式,则他、T(n)=o(n^k)
(3)For的时间复杂度等于循环次数乘以循环体代码的复杂度
(4)If---else结构的复杂度取决于if的条件判断复杂度和俩个分支的复杂度,总体复杂度取得是三段中的最大复杂度。