数据结构-初始篇

前言

    最近由于面试需要,所以重新学习了一遍数据结构,在此记录一下在学习过程中,总结的一些内容,供大家参考学习。

一、什么是数据结构?

    根据百度百科的描述,对数据结构做出如下定义,
    数据结构(data structure)是带有结构特性的数据元素的集合,它研究的是数据的逻辑结构和数据的物理结构以及它们之间的相互关系,并对这种结构定义相适应的运算,设计出相应的算法,并确保经过这些运算以后所得到的新结构仍保持原来的结构类型。简而言之,数据结构是相互之间存在一种或多种特定关系的数据元素的集合,即带“结构”的数据元素的集合。“结构”就是指数据元素之间存在的关系,分为逻辑结构和存储结构。


     简单的抽出几个关键词语,数据元素的集合,逻辑结构,物理结构,数据之间的关系,算法。这几个关键词就是数据结构研究的主要对象和内容了。数据元素的集合,从字面上理解就是一堆数据,那么这一堆数据有什么用呢?这就涉及到数据集合元素的关系了也就是数据的逻辑结构,在数据结构中,对数据之间的关系做出了归纳,数据之间的关系无外乎集合,线性结构,树型结构,图状结构这四种关系。这里对这几种关系进行解释。
  1. 集合
        集合关系,数据集合内的元素之间没有其它关联,也就是在一个集合内,数据元素之间没有什么关系。如图所示,各个元素之间没任何的联系。

在这里插入图片描述

  1. 线性结构
        线性结构在生活中较为常见,比如食堂排队的时候,排队同学之间就构成了线性结构的关系,除了队头和队尾的同学,每个同学前后都有一个同学。就像下面这张图片所示,元素之间的关系是前后相邻的线性关系。
    在这里插入图片描述

  2. 树型结构
        树型结构可以看成是层次结构,这样的结构多见于单位和机构,分层次的管理,元素之间的关系类似于上下级的关系,就拿学校而言,学校这个单位,最大的就是校长了,校长下面有副校长,副校长又管理多个处,处又包含若干的科。这就是一种分层次的结构关系。如图所示
    在这里插入图片描述

  3. 图状结构
        图状结构较常见与城市交通方面,每个建筑物或者城市可以看成一个数据,而从一个城市到另一个城市或者从一个建筑到另一个建筑之间有若干的路线(马路),这个路线就是这两个数据之间的关系,所以图状结构数据元素之间的关系可以是多个关系的。如图所示,各个元素之间的关系是任意的。
    在这里插入图片描述
        了解完数据之间的关系,那么问题来了,我们是搞计算机的,那怎么样才能在计算机内存储这些数据。学过C语言的同学会说到,拿数组存数据呗。确实,通过数据可以保存数据,然而这并不是唯一的存储方法,学过C语言的同学因该了解过指针,通过指针我们可以找到数据所在的地址,然后获取到数据元素的值,那好办了,就拿线性结构来说,如果我每个元素都存放了下一个元素的地址,那我不就是可以从第一个元素一直遍历到所有的元素,通过存放下一个元素的指针找到下一个元素。好家伙,确实可以。这样的结构就类似于图下所示:每个数据节点都存放有下一个数据元素的指针,这样就可以借助这个指针找到对应的元素,同理树型结构和图状结构也可以借助指针,找到相关联的元素。上述两个方法数组存放和通过指针就是存储结构的顺序存储和链式存储,通过顺序存储借助的是一块连续的内存空间,而通过链式存储则是通过指针来表示元素之间的关系,并且链式存储数据之间的地址并不一定是连续的是任意的。因为只要我有你的地址随你在哪都可以找到你。
    在这里插入图片描述
        在计算机存储了上述元素之后能干点啥事情吗?不能光存放起来,肯定要搞点事情啊。嗯,这就涉及到算法了,也就是对数据元素的操作。算法的定义是——“算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。”,简单的说算法就是执行方法的步骤。

二、算法的特性

一个算法应该具有以下五个重要的特征:
(1) 有穷性(Finiteness)
    算法的有穷性是指算法必须能在执行有限个步骤之后终止;
(2)确切性(Definiteness)
    算法的每一步骤必须有确切的定义;
(3)输入项(Input)
    一个算法有0个或多个输入,以刻画运算对象的初始情况,所谓0个输入是指算法本身定出了初始条件;
(4)输出项(Output)
    一个算法有一个或多个输出,以反映对输入数据加工后的结果。没有输出的算法是毫无意义的;
(5)可行性(Effectiveness)
    算法中执行的任何计算步骤都是可以被分解为基本的可执行的操作步骤,即每个计算步骤都可以在有限时间内完成(也称之为有效性)。

三、时间复杂度和空间复杂度

    时间复杂度和空间复杂度分析的对象是算法。对于算法的时间复杂度通常通过渐近的算法时间复杂度进行估计算法的时间复杂度。算法时间复杂度有几个符号需要了解。大O符号,大O符号描述的算法时间复杂度渐近的上界,也就是f(n) = O(g(n)),其中 f(n) <= g(n),可以理解为g(n)就是f(n)的渐近的上界。大Ω符号则表示总大于,来描述一个函数数量级的渐近下界。大Θ符号用于描述算法的精确界,也就是算法准确的阶数。进行算法时间复杂度分析的步骤如下:

  1. 选择基本操作,也就是以什么为操作去估计算法的时间复杂度,是赋值操作还是加法运算,是乘法运算还是除法运算,还是循环次数作为算法时间复杂度的评价标准。
  2. 然后分析算法执行过程中,基本操作的执行次数f(n),通过f(n)作为算法在以基本操作为标准下的时间复杂度。

这里给出几个例子:
for(i = 0 ; i < n ; i++){
     a = a+1 ; 
 }

以赋值运算作为基本操作来分析:则执行的加法操作次数为n次。则对应的f(n)函数为f(n) = n ;
根据f(n) = O(g(n)) ; 则对应的时间复杂度为O(n) 。

for(i = 0 ; i < n ; i++){
   for(j=0;j<i;j++){
   
   }
}

这里以循环体执行次数进行估计算法的时间复杂度,则执行次数f(n) = Σi ,的 f(n) = n*(n-1)/2,则对应的时间复杂度为O(n^2)

对于空间复杂度,也就是算法在执行过程中临时占用额外的空间,S(n)=O(f(n)),例如上述两个程序在运行过程除变量外,未占用额外空间,则空间复杂度未S(n) = O(1)。
如果将第二个程序改成如下形式:

for(i = 0 ; i < n ; i++){
  for(j=0;j<i;j++){
  	int a[i[ ;
  }
}

在算法执行过程中,每次都需要创建新的数组a[i],则耗费的额外的空间数为S(n)=n*(n-1)/2,即空间复杂度为S(n) = O(n^2)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值