数据结构——初识数据结构——第1章 绪论(1)

本文介绍了数据结构的起源和发展,详细阐述了数据、数据元素、数据项、数据对象和数据结构的概念。讨论了逻辑结构与存储结构,如集合、线性、树形和图形结构,以及顺序和链式存储。同时,讲解了数据类型和抽象数据类型,以及算法的设计、特性与效率分析,包括时间复杂度和空间复杂度的计算方法。
摘要由CSDN通过智能技术生成

1.数据结构的起源与发展

数据结构:为了设计出高效的程序,需要对计算机程序加工的数据对象进行系统的研究,即研究数据的特性以及数据之间存在的关系,此即数据结构。

2.基本概念和术语

2.1 数据

数据是能够被输入到计算机中且能被计算机识别并进行加工处理的符号集合,是计算机操作对象的总称。
举例:数值信息:整形、实型数值;非数值信息:图像、声音和文字。
对于数值型数据,可以直接进行处理;对于非数值的数据,可以通过编码将其变成数值型数据,再进行处理。

2.2 数据元素

数据元素是数据的一个基本单位,在计算机中作为一个整体进行考虑和处理。
成员里面的类型可以相同,也可以不同。

2.3 数据项

数据元素可以由若干项构成,这些项是构成护具元素的单位,即为数据项。
数据项可以是原子项,也可以是组合项,组合项可以分割为更小的数据项。

2.4 数据对象

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

2.5 数据结构

结构即指关系。所谓数据结构,简单地说是指相互之间存在某种逻辑关系的数据元素的集合。

2.6 小节

综上所述,不难看出:数据包含数据对象,数据对象包含数据元素,数据元素包含数据项。
在这里插入图片描述

3. 理解数据结构

程序设计(计算机求解问题)的步骤:
1.首先要从具体问题抽取一个恰当的数学模型;
2.其次分析需要完成的功能,设计一个或者一组对应功能的算法,并对算法进行分析优化;
3.最后编出程序,进行测试和调整,直至得到最终解答。

寻求数学模型实质就是分析问题,从中提取操作的数据对象,并找出数据对象中的数据元素之间蕴含的关系,并加以描述。这实际上是对数据结构进行分析与描述。

4.数据的逻辑结构和存储结构

4.1 逻辑结构

数据结构是对数据元素之间的逻辑关系的描述,是从具体问题抽象出来的数学模型,与数据的存储无关。
逻辑结构可以用一个数据元素的集合和定义在此集合上的若干关系来表示,如图形表示、二元组表示和语言描述等。

基本的数据结构有以下四种:

(1)集合结构。数据对象中的数据元素之间除了同属于一个集合之外,没有任何其他关系。这种结构类似于数学中的集合。

(2)线性结构。数据对象中的数据元素之间存在一对一的线性关系。

(3)树形结构。数据对象中数据元素之间存在一对多的层次关系。

(4)图形结构,也称为网状结构。指数据对象中数据元素之间存在多对多的任意关系。

数据的逻辑结构描述有:图形法和元组进行描述。

4.2 存储结构

分析和研究数据结构的最终目的是为了使计算机能对其进行处理。为此,仅有数据的逻辑结构是不够的,还必须研究这些结构在计算机内的存储方式,即存储结构,也称为物理结构。需要注意的是,数据的结构应能正确反映数据元素之间的逻辑。换句话说,需要存储的内容包含两部分:“数据对象”的存储以及“数据元素之间关系”的存储。

数据的存储结构的常用形式有四种: 顺序结构、链式结构、索引存储和哈希存储。

4.2.1 顺序存储结构

把逻辑上相邻的数据元素存储在物理位置相邻存储单元中,数据元素之间的逻辑关系由邻接关系来体现。顺序结构是一种最基本的存储表示方法,借助数组便可实现。

4.2.2 链式存储结构

把数据元素放在任意的存储单元中,逻辑上相邻的元素其物理位置可能相邻,也可能不相邻,而元素逻辑上的邻接关系在物理存储上通过附设的指针字段来表示

5. 数据类型和抽象数据类型

计算机求解问题的主要步骤,大体分为四个阶段:

(1)首先需要进行系统分析,即明确系统应该具有的功能和各个功能所操作的数据对象。
(2)其次系统设计阶段,对系统的数据结构进行分析与设计,即抽离处数据对象、数据元素之间的关系以及在数据对象上需要定义的操作。
(3)接着系统实现,此阶段需要根据软件系统的规模和应用环境,选用一种程序设计语言,将抽象数据类型描述转换成该程序设计语言支持的数据类型描述,并进行软件系统包含的各功能模块的编码实现。
(4)最后进行系统测试,就可以投入使用。
在这里插入图片描述
在系统设计阶段,为了更加清楚第描述数据结构,可以采用一种统一的形式将
数据对象
数据元素之间的关系
以及在数据对象上的操作
表示出来,即采用抽象数据类型进行描述。

5.1 数据类型

数据类型:是一个值的集合和定义在这个值集上的一组操作的总称。
C语言中,按照取值的不同,数据类型可以分为两类:原子类型和结构类型。
原子类型是不可以在分解的基础类型,包括整形、实形、枚举类型和指针类型;
结构类型是由若干个类型组合而成的类型组合而成的类型,如数组和文件等。

从“数学抽象”的角度看,可称它是一个已经用某种语言实现了的“抽象数据类型”,它强调的是其本质特征、它所能完成的功能以及它与外部用户的接口(即外界使用它的方法)。

5.2 抽象数据类型

抽象数据类型,指一个数学模型以及定义在该模型上的一组操作。抽象数据类型的定义仅取决于它的一组逻辑特性,而与其在计算机内部如何表示和实现无关。

数据类型有两个重要特性:
(1)一个是数据抽象,用ADT描述程序处理的实体时,强调的是其本质的特征、它所能完成功能以及它与外部用户的接口;
(2)另一个是数据封装,将实体的外部 特性和其内部是想细节分离,并对外部用户隐藏其内部实现细节。

抽象数据类型可用以下三元组表示:
(D,S,P)
其中,D是数据对象,S是D上的关系集,P是对D的基本操作。
基本操作集通常包括初始化、插入、删除、查找和遍历等。

在本书中,采用的ADT定义形式为:

ADT抽象数据类型名
{
数据对象:数据元素的集合
数据关系:数据关系的集合
基本操作:操作函数的列表
}ADT抽象数据类型名

举例:
在这里插入图片描述

1~5.小节

在这里插入图片描述

6. 算法与算法效率分析

6.1 数据结构与算法的关系

学习数据结构的目的是,能够分析实际问题中所涉及的数据对象的特性,并将其在计算机中表示出来,然后设计合适的算法对它们进行加工操作,以完成各种功能。许多大型程序的构造经验表明,系统实现的困难程度和系统构造的质量都严重依赖于所设计的数据结构的优劣程度。

由于算法的设计仅取决于数据的逻辑结构,而与物理存储方式无关,因此在构造数学模型之后,便可以进行相应操作的算法设计,而算法的具体实现则依赖于数据采用的存储结构。

6.2 算法的定义

算法是指问题求解所需要的具体步骤或方法,它是规定的一个有限长的操作序列。也就是说,给定初始状态或输入数据,能够在有限时间内得出所要求或期望的终止状态或输出数据。

6.3 算法的5大特性

(1)输入。一个算法必须有零个或多个输入。
(2)输出。一个算法应有一个或多个输出,输出是算法进行信息加工后得到的结果。
(3)有穷性。算法的描述必须在有限步骤内完成任务,如果在描述的算法中出现死循环,则满足不了有限性。
(4)确定性。算法的描述必须无歧义,通常要求实际运行结果是确定的,以保证算法的实际执行结果完全符合问题需求。即在一定的条件下,只有一条执行路径,相同的输入只能有唯一的输出结果。
(5)可行性。又称有效性,即算法中描述的操作都可以通过把已经实现的基本运算执行有限次来实现。一个有效的算法是指能够通过程序运行并获得正确结果算法。如果一个特定算法的理论很成熟,可是复杂度太高,难以实现;或者即使勉强实现了它,程序运行也需要几十年甚至几百年的时间开销,那么,这个算法就很难说是一个有效的算法。

6.4 算法设计的要求

(1)正确性。正确算法分为四个层次:
a.程序中不包含语法错误;
b.程序对几组输入数据能够的出满足要求的输出结果。
c.程序对于精心选择的典例、苛刻甚至带有刁难性的几组输入数据能够得出满足要求的结果。
d.程序对于一切合法的输入数据都能得出满足要求的结果。
通常,将层次3作为一个算法是否正确的标准。
(2)可读性。算法设计的目的不仅是为了计算机执行,同时也为了人的阅读与交流。因此,算法应该便于人理解。
可读性强的算法更加便于调试,易于发现并修改错误,而晦涩难懂的程序易于隐藏较多的错误而难以调试。此外,现实中的软件系统通常较为庞大,很难独自完成,而是需要多人合作。如果一个算法的设计让人难以理解,绝大多数人都看不懂,则很难将其有效利用,最终也是“一潭死水”。
(3)健壮性。当输入数据不合法时,算法应当能够恰当地作出反应或进行相应处理,而不是产生莫名其妙的输出结果。同时,处理错误的方法不应是中断程序的执行,而是返回一个表示错误或错误性质的值,以便更高的抽象层次上进行处理。比如,输入的分式中的分母不应该是0,一旦出现了0,就应该马上做出相应的提示操作,而不是异常中断。
(4)高效率和低存储量需求。“效率”通常指的是算法执行时间,而“存储量”指的是算法指向过程中所需的最大存储空间,两者都与问题的规模有关。设计算法时,应尽可能使其具有较低的时间成本,并且具有较少的空间开销。

6.5 算法效率分析

6.5.1 事后统计法

事后统计法即对每个算法编制出相应的程序,并在计算机上运行,利用机器时钟计算出程序执行的时间,从而确定算法的效率。
缺点:
①对于每一个算法,都要编制好相应的程序并执行,这通常需要花费大量的时间精力,造成不必要的成本浪费。
②一些其他的因数容易掩盖算法本身的优劣势。比如:运行程序所选择的计算机、操作系统、编译器等不同,都会导致同一个算法的运行时间具有差异。
③运行程序时,选择适合的输入数据集非常困难。通常,不同的输入数据集将导致程序产生不同的执行时间,而且程序的运行效率也将随着数据规模的变化而发生相应变化。因此如果选择的数据不够全面、准确,往往很难正确评价算法本身的优劣性。

事后统计法较少被用于运行算法分析,多被用于算法实现后的实验验证中。

6.5.2 事前分析估计法

事前分析估计法即在算法设计完成后,并不需要编制程序,而只需采用统计方法运行算法效率的大致估算。

程序的运行时间取决于以下几个因素:
① 算法选用的策略。
②问题的规模。
③编写程序的语言。
④编译程序产生的机器代码质量。
⑤计算机执行指令的速度。
如果抛开计算机硬件和软件相关的因素,只考虑算法本身,则前两条是影响程序的运行时间的主要因素。对于某一个特定算法,其“运行时间”的大小只依赖于问题的规模(问题处理数据量的大小,通常用整数n表示),或者说它是问题规模的函数。

6.6 算法的时间复杂度

6.6.1 算法的时间耗费

算法的执行时间是由构造算法的所有语句的执行时间决定的,因此,可以进行如下估算。
算法所耗费的时间 = 算法中每条语句的执行时间之和
每条语句的执行时间 = 语句的频度 * 语句执行一次所需要的时间
其中,语句的频度即指语句的执行次数。

进行算法分析的时,只需要将每条语句的执行时间看作单位时间。这样,算法花费的时间与算法中语句的执行次数成正比,语句执行次数多,算法花费时间就多。

6.6.2 时间复杂度

一个特定算法的“运行工作量” 依赖于问题规模n,它是问题规模n的函数。T (n)表示的是特定算法的“运行工作量的函数”
若存在常量C>0,n0>0,当n>=n0时,T (n) ≤ C * f(n),则算法为f(n)阶,记为:T (n) = Ο(f (n)) ,T(n)即为算法的(渐近)时间复杂度。表示算法执行时间的增长率和f(n)的增长率相同。
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

6.6.3 时间复杂度的计算

通常。在算法中选取一种对于所研究的问题来说是“基本操作”的原操作,以该“基本操作”在算法中重复执行的次数作为算法运行时间的衡量准则,并计算其时间复杂度。下面给出时间复杂度的计算方法,

  1. 先求出所有代码的运行次数,通常是一个关于问题规模的表达式。
  2. 用常数1取代运行次数中的所有参数和。
  3. 在修改后的运行次数中,保留最高阶项。
  4. 如果高阶项存在且不是1,则去除与这个项相乘的常数。

(1)常数阶
单语句和分支结构。
T(n)=O(1)表示
(2)线性阶
循环结构
(3)对数阶
在这里插入图片描述

(4)平方阶
循环的嵌套;对于多重循环结构的程序段,只需要讨论最深层的语句执行的次数。

6.7 算法存储空间需求

空间复杂度定义为S(n)=O(g(n))。

算法在计算机存储器所占用的存储空间包括三个方面:
(1)存储算法本身所占用的存储空间;
(2)算法的输入输出数据所占用的空间;
(3)以及算法在运行过程中临时占用的存储空间。

空间复杂度是对算法在运行过程中临时占用存储空间大小的度量。

6的小节

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杰深入学习计算机

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值