数据结构与算法学习(绪论)

第一节 数据结构与算法绪论

程序设计=数据结构+算法

 

1、数据结构

数据结构:就是关系,数据结构相互之间存在的一种或者多种特定关系的集合。

1)逻辑结构:数据对象中各种元素间的相互关系。

四种逻辑结构:

集合结构:元素同属于一个集合。

线性结构:一对一的关系。

树形结构:一对多的层次结构。

图形结构:多对多的关系。

2)物理结构:数据的逻辑结构在计算机中存储形式。研究如何把数据元素存储到计算机存储器中。

存贮器主要是针对内存而言,像硬盘、软盘和关盘等外部存储器的数据组织通常用文件结构来描述。

 

2、数据结构存储的方式

数据结构存储的方式主要有两种:

1顺序存储结构:将数据元素存储在地址连续的存储单元中,数据间的逻辑关系和物理关系式一致的,如数组结构。

2)链式存储结构:是把数据元素存储在任意的存储单元中,这些存储单元可以是连续的,也可以是不连续的。显然,链式存储结构的数据结构的存储关系并不能反映其逻辑关系,需要一个指针存储数据元素的地址,通过地址就可以找到相关联数据元素的存放位置。

 

3、算法

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

对于给定的问题,解决问题的方法有多种。

方法一:

int i,Sum=0,int n=100; //执行1

for (i=1,i<=n,i++)  //执行n+1

Sum+=i;          //执行n

printf(‘%d’,Sum);  //执行1

执行1+n+1+n+1=2n+3

方法二:

int i,Sum=0,int n=100; //执行1

Sum=(1+n)*n/2; //执行1

printf(‘%d’,Sum); //执行1

执行1+1+1=3

 

算法的5特征

输入:有0个或者多个输入。

输出:至少有一个或者多个输出,

有穷性:只算法执行有限次后能够自动结束而不会出现无限循环,并且每一个步骤都可以在 有限的时间内执行完。

确定性:算法每一个步骤都有明确的含义,不会出现二义性;

算法在一定条件下,只有一条执行路径,相同的输入,只有唯一的结果

可行性:算法的每一个步骤都是可行的,每一步都可以通过执行有限次数完成。

 

算法设计的要求:

正确性:

4个层次:

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

2)对于给定的合法输入能够产生满足要求的输出

3)对于非法输入能够产生满足规格的说明

4)对于故意刁难的测试输入都有满足要求的输出结果。

可读性:便于阅读理解和交流

健壮性:输入不合法时,也能做出相应的处理,而不是产生异常,崩溃或者莫名奇妙的结果。

时间效率高和存储量低

 

 

第二节 算法效率度量方法

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

缺陷:实现编好测试程序,浪费时间和精力,测试环境差别比较大。

事前分析估算算法:在程序编写前,依据统计方法对算法进行估计。

影响因素:

算法采用的策略,方案

编译产生的代码质量

问题的输入规模

机器执行指令的速度

总之,除计算机软硬件因素外,一个程序运行的时间依赖于算法的好坏和问题的输入规模

 

我们研究的算法的复杂度、,侧重的事研究算法的随着输入规模扩大增长量的一个抽象,而不是精确的定位需要执行多少次。

不计那些循环索引的递增和循环终止条件,变量声明,打印结果等操作,重要的事将基本操作的数量和输入模式并联起来。

 

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

 

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

 

1、算法的时间复杂度

定义:在进行算法分析时,语句总的执行次数 T(n) 是关于问题规模n的函数,进而分析T(n) n的变化情况并确定T(n) 的数量级。

算法的时间复杂度,也就是算法的时间度量,记作:T(n)=O(f(n))。

它表示随问题规模n的增大,算法执行时间的增长率和f(n) 的增长率相同,称作算法的渐进时间复杂度,简称为时间复杂度。其中f(n)是问题规模n的某个函数。

O( )来体现时间复杂度的记法,我们称之为的O记法。

一般情况下,随着输入规模n的增长,T(n)增长最慢的算法为最优算法。

推导大O的阶:

1)用常数项取代运行时间中所有加法常数,

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

3)如果最高阶项存在且不为1,则去除与这个项相乘的常数

4)得到最后结果就是大O

 

常见的时间复杂度

常数阶:O(1)

线性阶:随着问题规模的增大,对应计算次数成直线增长,时间复杂度记为O(n)

平方阶:O(n^2)

循环的时间复杂度就等于循环体的复杂度乘以该循环运行的次数。

Int i,j,n=100

for(i=1,i<=n,i++)

{

for(j=i,j<=n,j++)

{

printf(“*”);

}

}

执行次数:N(n)=n+n-1+...+1=(1+n)*n/2=n^2/2+n/2=O(n^2)

对数阶:时间复杂度为O(logn)

int i=1,n=100

while(i<n)

{

i=i*2;

}

2^x=n

x=log(2)n,

nlogn阶:O(nlogn)

立方阶:O(n^3)

指数阶:O(2^n)

复杂度:常数阶 对数阶 线性阶 < nlogn阶 平方阶立方阶 指数阶

常用的时间复杂度所消费的时间从小到大依次为:

O(1) < O(logn) < O(n) < O( nlogn) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)

 

 

2、函数调用的时间复杂度分析

int i,j;

for (i=0,i<n,i++)//时间复杂度:O(n)

 

{

function(i);

}

void function(int count)//时间复杂度:O(1)

{

printf(“%d”,count);

}

function函数是如下的循环,那么,该算法的时间复杂度就为0(n^2)

void function(int count)//时间复杂度:0(n^2)

{

for(int j=count,j<n,j++)

{

printf(“*”);

}

}

 

最坏情况与平均情况

平均运行时间:是期望的运行时间。

最坏运行时间:是一种保证,在应用中,这是一整最重要的需求,通常除非特别指定,我们提到的运行时间都是最坏情况下得运行时间。

 

 

3、算法的空间复杂度

写代码时可以用空间来换取时间。

算法的空间复杂度通过计算算法所需要的存储空间实现,算法的空间复杂度的计算公式记作:

S(n)=O(f(n)),其中,n为问题规模,f(n)为语句关于n所站存储空间的函数。

通常,用“时间复杂度”来指运行时间的需求,是用“空间复杂度”只空间需求。

一般求“复杂度”时,通常是指“时间复杂度”。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值