数据结构和算法之成数据结构概论(一)

在诸多博客上不止一遍的看过 数据结构和算法对于程序员的重要性 不得不说 这是一门看起来很枯燥的东西 但是 这就是程序的基础 所谓万丈高楼平地起 最近在看一本数据结构和算法的书籍 边看边写博客作为笔记 也可时常温故而知新

数据结构

概念
每个数据对象中的数据元素都不是独立的,数据元素之间的内在联系成为结构。

数据的逻辑结构和存储结构
1.逻辑结构:
a.集合结构(元素同属于一个集合,无其他关系)
b.线性结构(一对一关系)
c.树形结构(一对多关系)
d. 图形结构(多对多关系)
2.存储结构
a.顺序存储(例如数组)
b.链式存储(例如泛型)

算法

定义

算法是对特定问题求解过程的描述,是指令的有限序列,为解决某一特定问题而采取的具体有限的操作步骤。
算法是一种解决问题的思想所在,用怎样的方式解决这个问题,这种想法就叫算法。在编程中,算法不一定是程序,但程序是算法。
算法的主要描述方式有以下4种:
a.框图算法描述(流程图或N-S图)
b.非形式算法描述(使用语言【中文英文和程序设计语言中的语句】描述算法)
c.类高级语言描述(例如C/C++/java)
d.使用高级语言描述(可在计算机运行并获得结果)

算法复杂度分析

为了比较不同算法的效率,计算机大佬们提出一种称为计算复杂性的方法度量算法的难度。算法的复杂性是度量算法效率、评价算法优劣的重要依据。计算机资源中最重要的是时间资源(处理器)和空间资源(存储器),算法的复杂性通常体现为时间复杂性和空间复杂性。
首先介绍一种方法:渐进算法分析
一般情况下,用来表示数据规模和时间关系的函数都相当的复杂。计算这样的函数时,通常只考虑大的数据,不能显著改变函数数量级的部分可以忽略,结果则为原函数的一个近似值,当数据规模很大时,也足以接近于原值。
例如下述函数:f(n)=n²+100n+100
当n取值足够大时,函数的值主要来源于n²
渐进分析最常用的表示方法是估计函数的增长趋势,采用了由Paul Bachmann于1984年引入的大0表示法
大0表示法给出了函数f(n)的严格上限。一般来说,可表示为f(n)=0(g(n))。表示当输入规模n很大时,f(n)的上界是g(n)。
怎样推导大0阶 有如下方法
a.用常数1取代运行时间中的所有加法常数
b.在修改后的运行次数函数中,只保留最高阶层
c.若最高阶层项存在且不是1,则去除与这个项相乘的常数。
得到的结果就是大0阶
几种常见的大0阶情况如下:
1.常数阶

int sum=0,n=100   //执行1次
    sum=(1+n)*n/2 //执行1次
system.out.printin(sum) //执行1次

这个算法的运行次数函数是f(n)=3,根据推导大0阶的方法 ,第一步就是把常数项3改为1,由于没有最高项,所以该算法的时间复杂度为0(1)

2.线性阶

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

上述这段代码,算法复杂度为0(n),因为循环体中的代码必须要执行n次

3.平方阶

int i,j;
int sum=0;
for(i=0;i<n;i++)
{
     for(j=0;j<n;j++)
     {
        sum=sum+i*j;
     }
 }

内循环已分析过,复杂度是0(n),对于外层循环来说,试着复杂度为0(n)的语句再循环n次,所以这段代码的复杂度为0(n²)。同理,若外循环的循环次数改为m,则时间复杂度为0(m*n)

4.对数阶

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

每次count*2后离n更近。有多少个2相乘之后大于n,则退出循环。则有:2x=n 则x=log2n 这个循环的时间复杂度则为0(logn)

算法特性及设计要求

算法特性:
a.输入输出(算法的输入可以是0个,但是算法一定要有输出,输出形式可以为打印或者返回值等)
b.有穷性(算法有有限的执行步骤,且每一步骤在可接受的时间内完成)
c.确定性(每一步骤有其确定的含义,同一输入必须是同一输出结果)
d.可行性(每一步骤可行,意味算法可以转换成程序上机运行,且得到正确结果)
好的算法有以下几个标准:
a.正确性
b.可读性
c.健壮性
d.最佳时间复杂度和空间复杂度(时间效率高存储量低)

递归

定义

递过去一个方法,则归还回来一个值。这是递归思想的精华所在。
递归有四特性:
a.必须有可最终达到的终止条件,否则是一个死循环
b.子问题在规模上比原问题小,或更接近于终止条件
c.子问题可通过再次递归调用求解或因满足终止条件而直接求解
d.子问题的解应能组合为整个问题的解
一个函数在解决问题时,自身调用到自身,则为递归。

递归函数的格式

函数不再递归的情况称为基本情形
函数调用自身来执行子任务的情况称为递归情形
可用如下的形式来描述所有的递归函数:

if(判断是否为基本情形)
    return 该基本情形时函数的值
else if(判断是否为另一种基本情形)
    return 该基本情形时函数的值
//递归情形
else
    return(执行某些工作并递归调用)

猜你喜欢

转载自blog.csdn.net/My_ben/article/details/82181809