数据结构与算法

1.1数据结构的研究内容

程序=数据结构+算法   ———程序的本质

 

例1:图书管理系统

操作对象:若干行数据记录

操作算法:查询、插入、删除、修改等

操作对象之间的关系:线性关系

数据结构:线性数据结构线性表

例2:文件系统的结构图

如图可以看到,这是一个典型的树型结构问题,数据与数据成一对多的关系,是一种典型的非线性关系——树型结构

例3:地图导航寻找最短路径

 

操作对象:各地点及路的信息

算法:设置信号灯,求各可通行的路的集合

关系:非线性关系、网状结构

综上:

数据结构是一门研究非数值计算的程序设计中计算机的操作对象以及它们之间的关系操作的学科。

1.2.1数据、数据元素、数据项和数据对象

1.数据(Data)

是输入计算机且能被计算机处理的各种符号的集合,这个集合包括数值型的数据(整数、实数等)和非数值型的数据(文字、图像等)

        信号的载体

        是对客观事实符号化的表示

        能够被计算机识别、存储和加工

2.数据元素(Data element)

数据的基本单位,在计算机程序中通常作为一个整体进行考虑和处理。

也可以被称为元素、记录、结点(树)、顶点(图)。

一个数据元素可由若干数据项组成。

3.数据项(Data Item)

构成数据元素的最小单位。

数据、数据元素、数据项之间的关系:

数据 > 数据元素 > 数据项

4.数据对象(Data Object)

是性质相同的数据元素的集合,是数据的一个子集。

例:整数的数据对象是集合N={0,+1,-1,+2,-2......}

数据元素与数据对象

数据元素——组成数据的基本单位

        与数据的关系:是集合的个体

数据对象——性质相同的数据元素的集合

        与数据的关系:集合的子集

1.2.2数据结构(Data Structure)

(1)数据元素不是孤立存在的,它们之间存在着某种关系,数据元素相互之间的关系称为结构

(2)是指相互之间存在一种或多种特定关系的数据元素集合

(3)也可以理解为数据结构是带结构的数据元素的集合

1.内容

(1)数据元素之间的逻辑关系,也称为逻辑结构

(2)数据元素及其关系在计算机内存中的表示(映像),称为数据的物理结构存储结构

(3)数据的运算和实现,即对数据元素可以施加的操作以及这些操作在相应的存储结构上的实现。

2.两个层次

(1)逻辑结构

描述数据元素之间的逻辑关系

与数据存储无关,独立于计算机

是从具体问题抽象出来的数学模型

种类

(2)存储结构

数据元素及其关系在计算机存储器的结构

是数据结构在计算机中的表示

四种基本存储结构

①顺序存储

用一组连续的存储单元依次存储数据元素,数据元素之间的逻辑关系由元素的存储位置来表示。

例:C语言中通常用数组来实现顺序存储。

②链式存储结构

用一组任意的存储单元存储数据元素,数据元素之间的逻辑关系用指针来表示。

例:C语言中通常用指针来实现。

③索引存储结构

在存储结点信息的同时,还建立附加的索引表。

索引表中每一项称为一个索引项。

索引项的一般形式(关键字、地址)

关键字是能唯一标识一个结点的那些数据项。

稠密索引:每个结点在索引表中都有一个索引项。

稀疏索引:一组结点在索引表中只对应一个索引项。

④散列存储结构

根据结点关键字直接计算出该结点的存储地址。

关系

存储结构是逻辑关系的映像与元素本身的映像。

逻辑结构是数据结构的抽象,存储结构是数据结构的实现。

逻辑结构与存储结构共同建立了数据元素之间的结构关系。

1.2.3数据类型和抽象数据类型

程序中出现的变量、常量、表达式,我们都需要明确说明它们所属的数据类型

例:int、char等基本数据类型

        数组、结构、共用体、枚举等构造数据类型

        typedef,自己定义数据类型

数据类型作用:(1)约束变量或常量的取值范围;(2)约束变量或常量操作。

数据类型(Data Type)

定义:是一组性质相同的值的集合,以及定义于这个值集合上的一组操作的总称。

        数据类型=值的集合+值集合上的一组操作

抽象数据类型(Abstract Data Type,ADT)

是指一个数学模型以及定义在此数学模型上的一组操作。

·由用户定义,从问题抽象出数据模型(逻辑结构)

·定义在数据模型上的一组抽象运算(相关操作)

·不考虑计算机内的具体存储结构与运算的具体实现算法

形式定义

可用(D、S、P)三元组表示

        D——数据对象

        S——D上的关系集

        P——对D的操作

定义格式

ADT 抽象数据类型名{

        数据对象:<数据对象的定义>

        数据关系:<数据关系的定义>

        基本操作:<基本操作的定义>

} ADT 抽象数据类型名

基本操作的定义格式:

基本操作名 (参数表)

初始条件:(初始条件描述)

操作结果:(操作结果描述)

说明:

参数表:赋值参数,只为操作提供输入值。

               引用参数 以&开头,可以提供输入值和返回操作结果。

初始条件:描述操作之前数据结构和参数应满足的条件,若不满足,操作失败,返回相应出错信息。当初始条件为空,省略。

操作结果:说明操作正常之后,数据结构的变化状况和应返回的结果。

例:Circle的定义

ADT 抽象数据类型名{                                        ADT Circle{

        Data                                                                数据对象:D={r,x,y|r,x,y均为实数}

          数据对象的定义                                            数据关系:R={<r,x,y>|r是半径,<x,y>圆心坐标}

          数据元素之间逻辑关系定义                          基本操作:

        Operation                                                       Circle(&C,r,x,y)

          操作1                                                                        操作结果:构造一个圆

                初始条件                                                double Area(C)

                操作结果描述                                                      初始条件:圆已存在。

          操作 2                                                                       操作结果:计算面积。

                ......                                                        double Circumference(C)

          操作n                                                                        初始条件:圆已存在。

                ......                                                                     操作结果:计算周长。

} ADT 抽象数据类型名                                       }

C语言描述,用已有的数据类型定义描述存储结构,用函数描述操作。

例:用C实现抽象数据类型

typedef struct
{
    float realpart;                    /*实部*/
    float imagpart;                    /*虚部*/
}Complex;

void assign (Complex * A, float real , float imag);    /*赋值*/
void add (Complex * A, float real , float imag);    /*A+B*/
void minus (Complex * A, float real , float imag);    /*A-B*/
void multiply (Complex * A, float real , float imag);    /*A*B*/
void divide (Complex * A, float real , float imag);    /*A/B*/

void assign (Complex * A, float real , float imag)
{
    A->realpart = real;                /*实部赋值*/
    A->imagpart = image;                /*虚部赋值*/
}

void add (Complex *c, Complex A, Complex B)    /* c = A + B */
{
    c->realpart = A.realpart + B.realpart;        /*实部相加*/
    c->imagpart = A.imagpart + B.imagpart;        /*虚部相加*/
}

注:Complex是自己定义的结构体类型

        带*:指针变量,指向Complex类型的指针

        不带*:普通变量。

1.3算法和算法分析

1.3.1算法的定义

对待特定问题求解方法和步骤的一种描述,它是指令的有限序列。其中每个指令表示一个或多个操作。简而言之,算法是解决问题的方法和步骤

1.3.2算法与程序

算法是解决问题的一种方法或一个过程,考虑如何将输入转换成输出,一个问题有多种算法。

程序是用某种程序设计语言对算法的具体实现。 

                                        程序=数据结构+算法

                                   数据结构通过算法实现操作 

                                   算法根据数据结构设计程序

1.算法的五个特性

2.算法设计的要求

正确性、可读性、健壮性、高效性

一个算法主要考虑算法的效率

1.时间效率:指算法所耗费的时间

2.空间效率:算法执行过程中所耗费的存储空间

时间效率和空间效率有时候是矛盾的。

3.算法时间效率的度量

该算法编制的程序在计算机上执行所消耗的时间

方法:事后统计、事前统计(一般用它)

事前分析法

        算法运行时间=一个简单操作所需时间*简单操作次数

即:算法中每条语句的执行时间之和

        算法运行时间=\sum每条语句的执行次数(语句频度)*该语句执行一次所需的时间

由于每条语句执行一次的时间由机器本身软硬件环境决定,与算法无关,所以,假设执行每条语句所需时间均为单位时间,此时算法运行时间为语句频度之和。

例:连个n*n矩阵相乘的算法可描述为

for(i=1;i<n;i++)                                    //n+1次
    for(j=1;j<n;j++)                                //n(n+1)次
    {
        c[i][j]=0;                                  //n*n次
        for(k=0;k<n;k++)                            //n*n*(n+1)次
            c[i][j]=c[i][j]+a[i][k]*b[k][j];        //n*n*n次
    }

时间消耗T(n)=2n^{3}+3n^{2}+2n+1 

4.时间复杂度

有某个辅助函数f(n),n\rightarrow \infty,T(n),f(n)极限值为不等于零的常数,f(n)是T(n)的同数量级函数。记作T(n)=O(f(n)),O(f(n))称为算法渐进时间复杂度,简称时间复杂度。

        定义:算法中基本语句重复执行的次数问题规模n的某个函数f(n),记作 T(n)=O(f(n)),表示随着n增大,算法执行时间增长率和f(n)的增长率相同,称渐进时间复杂度。

5.分析算法时间复杂度的基本方法

1.找出语句频度最大的那条语句作为基本语句

2.计算基本语句的频度得到问题规模n的某个函数f(n)

3.取其数量级用符号“O”表示

例1

for(i=1;i<=n;i++)
    for(j=1;j<=i;j++)
        for(k=1;k<=j;k++)
            x=x+1;

解:(1)语句频度最大的语句:x=x+1;

       (2)语句频度=\sum_{i=1}^{n}\sum_{j=1}^{i}\sum_{k=1}^{j}1=\sum_{i=1}^{n}\sum_{j=1}^{i}j=\sum_{i=1}^{n}\frac{i(i+1)}{2} =\frac{n(n+1)(n+2)}{6}

       (3)时间复杂度O(n^3)

例2

i=1;
while(i<=n)
    i=i*2;

 解:先找出语句频度最大的语句:i=i*2;

        关键找出执行次数x与n的关系,并表示成n的函数

        若循环1次:i=1*2=2;

        若循环2次:i=2*2=2^2;

        若循环3次:i=2*2*2=2^3;

        若循环x次:i=2^x.

        i<=n,

        \therefore2^x=n,

        \thereforex<=\log_{2}n

        即:f(n)\leq \log_{2}n,取最大值f(n)\leq \log_{2}n

        \therefore该程序的时间复杂度T(n)=O(\log_{2}n)

注:有些情况下,算法中基本操作重复执行的次数还随问题的输入数据集不同而不同

例:顺序查找

for(i=0;i<n;i++)
    if(a[i]==e)
        return i+1;    //找到,返回是第几个元素
return 0;

最好情况:1次;最坏情况:n次。平均时间复杂度O(n)。

一般情况下考虑最坏情况下的时间复杂度,以保证算法的运行时间不会比它更长。

对于复杂的算法,利用加法法则乘法法则,计算时间复杂度 :

a)加法规则

T(n)=T1(n)+T2(n)=O(f(n))+O(g(n))=O(max(f(n),g(n)))

b)乘法规则

T(n)=T1(n)*T2(n)=O(f(n))*O(g(n))=O(f(n)*g(n))

6.算法时间效率的比较

时间复杂度按数量级递增顺序:

复杂度低——————————————————————————————————>复杂度高

7.渐进空间复杂度

空间复杂度:算法所需存储空间的度量,

                记作:S(n)=O(f(n)), n为问题的规模

算法要占据的空间:

(1)算法本身要占据的空间,输入/输出,指令,常数,变量等。

(2)算法要使用的辅助空间

例:将一维数组a中的n个数逆序存放到原数组中。

算法1:S(n)=O(1)

for(i=0;i<n/2;i++)
{
    t=a[i];
    a[i]=a[n-i-1];
    a[n-i-1]=t;
}

算法2:S(n)=O(n) 

for(i=0;i<n;i++)
    b[i]=a[n-i-1];
for(i=0;i<n;i++)
    a[i]=b[i];

1.4设计好算法的过程

  • 43
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值