【数据结构与算法】(一)数据结构相关的基本概念

文章目录

  • 【数据结构与算法】(一)数据结构相关的基本概念
    • 前言
    • 1.1 数据结构的研究内容
    • 1.2 基本概念和术语
      • 1.2.1 数据、数据元素、数据项和数据对象
      • 1.2.2 数据结构
      • 1.2.3 数据类型和抽象数据类型
    • 1.3 抽象数据类型的表示与实现
    • 1.4 算法和算法分析
      • 1.4.1 算法的定义及特性
      • 1.4.2 评价算法优劣的基本准则
      • 1.4.3 算法的效率分析(时间复杂度、空间复杂度)
    • 1.5 个人小结(不定期更新)
      • 1.5.1 时间复杂度与空间复杂度的计算

【数据结构与算法】(一)数据结构相关的基本概念

前言

本篇文章大部分内容摘自严蔚敏、李冬梅、吴伟民编著的由人民邮电出版社出版发行的《数据结构:C语言版|第2版》,少部分摘自《王道2025数据结构考研复习指导》,也有部分内容为本人的思考。

如果觉得本篇文章对你有帮助的话,不妨点赞、收藏加关注吧!😘❤️❤️❤️

1.1 数据结构的研究内容

简单的说,数据结构是一门研究非数值计算程序设计中的操作对象以及这些对象之间的关系和操作的学科。

1.2 基本概念和术语

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

  • 数据(Data):数据是客观事物的符号表示,是所有能输入到计算机中并被计算机程序处理的符号的总称。
  • 数据元素(Data Element):数据元素是数据的基本单位,在计算机中通常作为一个整体进行考虑和处理。
  • 数据项(Data Item):数据项是组成数据元素的、有独立含义的、不可分割的最小单位。
  • 数据对象(Data Object):数据对象是性质相同的数据元素的集合,是数据的一个子集。

1.2.2 数据结构

数据结构(Data Structure)是相互之间存在一种或多种特定关系的数据元素的集合。简单来说,数据结构是带“结构”的数据元素的集合,“结构”就是指数据元素之间存在的关系。

数据结构包括逻辑结构和存储结构两个层次。

一、逻辑结构

逻辑结构是从逻辑上描述数据,它与数据的存储无关,是独立于计算机的。因此,数据的逻辑结构可以看做是从具体问题抽象出来的数学模型。

数据的逻辑结构有两个要素:一是数据元素;二是数据元素之间的逻辑关系。

根据数据元素之间关系的不同特性,通常有四类基本结构:

  1. 集合结构:数据元素之间除了“属于同一集合”的关系外,没有其他任何关系。
  2. 线性结构:数据元素之间存在一对一的关系。
  3. 树结构:数据元素之间存在一对多的关系。
  4. 图结构(网状结构):数据元素之间存在多对多的关系。

其中,集合结构、树结构、图结构(网状结构)都属于非线性结构。

线性结构主要为线性表及线性表的变体(如栈、队列、数组、广义表等)。

二、物理结构(存储结构)

数据对象在计算机中的存储表示称为数据的存储结构,也称物理结构。把数据对象存储到计算机时,通常要求既要存储数据元素的数据,又要存储数据元素之间的逻辑关系,数据元素在计算机内用一个结点来表示。

数据元素在计算机中有两种基本的存储结构,分别是顺序存储结构和链式存储结构。

  1. 顺序存储结构:顺序存储结构是借助元素在存储器中的相对位置来表示数据元素之间的逻辑关系,通常借助程序设计语言的数据类型来描述。顺序存储结构要求所有的元素依次存放在一片连续的存储空间中。
  2. 链式存储结构:相对于顺序存储结构,链式存储结构无需占用一整块存储空间。但为了表示结点之间的关系,需要给每个结点附加指针字段,用于存放后继元素的存储地址。所以链式存储结构通常借助于程序设计语言的指针类型来描述。

当然,在有些书籍中,也把顺序存储结构、链式存储结构、索引存储结构和散列存储结构作为数据元素的四种基本存储结构。

索引存储结构:索引存储结构在存储元素信息的同时,还建立附加的索引表。索引表中的每项称为索引项,索引项的一般形式是(关键字,地址)。其优点是检索速度快;缺点是附加的索引表额外占用存储空间。另外,增加和删除数据时也要修改索引表,因而会花费较多的时间。

散列存储结构:散列存储指的是根据元素的关键字直接计算出该元素的存储地址,又称哈希(Hash)存储。其优点是检索、增加和删除结点的操作都很快;缺点是若散列函数不好,则可能出现元素存储单元的冲突,而解决冲突会增加时间和空间的开销。

存储密度:所谓存储密度是指数据元素本身所占用的存储量和整个结点结构所占用的存储量之比。

即 存储密度 = 数据元素本身占用的存储量 / 结点结构所占用的存储量

由于链式存储结构还需要额外存储结点附加指针字段,因此,一般来说,顺序存储结构的存储密度都要大于链式存储结构的存储密度。

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

  1. 数据类型:

数据类型(Data Type)是高级程序设计语言中的一个基本概念,例如前文提到的顺序结构可以借助程序设计语言的数组类型描述,链式存储结构可以借助指针类型描述,所以数据类型和数据结构的概念密切相关。

简单来说,数据类型是一个值得集合和定义在这个值集上一组操作的总称。类型明显或隐含地规定了数据的取值范围、存储方式以及允许进行的运算。

  1. 抽象数据类型

抽象数据类型(Abstract Data Type,ADT)一般指由用户定义的、表示应用问题的数学模型,以及定义在这个模型上的一组操作的总称,具体包括三部分:数据对象、数据对象上关系的集合以及对数据对象的基本操作的集合。

抽象数据类型的定义格式如下:

ADT 抽象数据类型名{数据对象:<数据对象的定义>数据关系:<数据关系的定义>基本操作:<基本操作的定义>
}ADT 抽象数据类型名

其中,数据对象和数据关系的定义采用数学符号和自然语言描述,基本操作的定义格式为:

基本操作名 <参数表>初始条件:<初始条件描述>操作结果:<操作结果描述>

基本操作有两种参数:赋值参数只为操作提供输入值;引用参数以“&”打头,除可提供输入值外,还将返回操作结果。

“初始条件”描述了操作执行之前数据结构和参数应满足的条件,若初始条件为空,则省略。

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

1.3 抽象数据类型的表示与实现

运用抽象数据类型描述数据结构,有助于在设计一个软件系统时,不必首先考虑其中包含的数据对象,以及操作在不同处理器中的表示和实现细节,而是在构成软件系统的每个相对独立的模块上定义一组数据和相应的结构。这和
面向对象方法的思想是一致的,所以表示和实现抽象数据类型,最好用面向对象的方法,比如用C++语言的类描述比较方便、有效。

1.4 算法和算法分析

数据结构和算法之间存在着本质联系。在“数据结构”中,将遇到大量的算法问题,因为算法联系着数据在计算过程中的组织方式,为了描述实现某种操作,常常需要设计算法,因而算法是研究数据结构的重要途径

1.4.1 算法的定义及特性

算法(Algorithm)是为了解决某类问题而规定的一个有限长的操作序列。

一个算法必须满足以下5个重要特性。

  1. 有穷性:一个算法必须总是在执行有穷步后结束,且每一步都必须在有穷时间内完成。
  2. 确定性:对于每种情况下所应执行的操作,在算法中都有确切的规定,不会产生二义性,使算法的执行者或阅读者都能明确其含义及如何执行。
  3. 可行性:算法中的所有操作都可以通过已经实现的基本操作运算执行有限次来实现。
  4. 输入:一个算法有零个或多个输入。当用函数描述算法时,输入往往是通过形参表示的,在它们被调用时,从主调函数获得输入值。
  5. 输出:一个算法有一个或多个输出,它们是算法进行信息加工后得到的结果,无输出的算法么有任何意义。当用函数描述算法时,输出多用返回值或引用类型的形参来表示。

1.4.2 评价算法优劣的基本准则

一个算法的优劣应该从以下几个方面来评价。

  1. 正确性:在合理的数据输入下,能够在有限的运行时间内得到正确的结果。
  2. 可读性:一个好的算法,首先应便于人们的理解和相互交流,其次才是机器的可执行性。可读性强的算法有助于人们对算法的理解,而难懂的算法易于隐藏错误,且难于调试和修改。
  3. 健壮性:当输入的数据非法时,好的算法能适当地做出正确反应或进行相应处理,而不会产生一些莫名其妙的输出结果。
  4. 高效性:高效性包括时间和空间两个方面。时间高效是指算法设计合理,执行效率高,可以用时间复杂度来度量;空间高效是指算法占用存储容量合理,可以用空间复杂度来度量。时间复杂度和空间复杂度是衡量算法的两个主要指标。

1.4.3 算法的效率分析(时间复杂度、空间复杂度)

算法效率分析的目的是看算法实际是否可行,并在同一问题存在多个算法时,可进行时间和空间性能上的比较,以便从中挑出较优算法。

衡量算法销量的方法主要有两类:事前分析估算法和事后统计法。事后统计法需要先将算法实现,然后测算其时间和空间开销,缺陷明显,因此我们通常采用事前分析估算法,通过计算算法的渐近复杂度来衡量算法的效率。

时间复杂度

在不考虑计算机软硬件等环境因素,影响算法时间代价的最主要因素是问题规模。问题规模是算法求解求解问题输入量的多少,一般用整数n表示。

一个算法的执行时间大致上等于其所有语句执行时间的总和,而语句的执行时间则为该条语句的语句频度(Frequency Count,代表该语句重复执行的次数)乘以语句执行一次所需的时间。

设每条语句执行一次所需的时间均为单位时间t,则一个算法的执行时间可以用该算法中所有语句的频度之和来度量。

例如:

for(i = 1; i<=n; i++){  // 频度为 n + 1for(j = 1; j<=n; j++){ // 频度为 n*(n+1)c[i][j] = 0; // 频度为 n^2for(k = 1; k<=n; k++){ // 频度为 n^2 * (n + 1)c[i][j] = c[i][j]+a[i][k]*b[k][j]; // 频度为 n^3}}
}

该算法中所有语句频度之和是关于n的函数,我们用f(n)表示,则f(n) = 2n^3 + 3n^2 + 2*n + 1。

所以问题规模为n时,该算法的执行时间为f(n) * t

但由于语句的执行要由源程序经编译程序翻译成目标代码,目标代码经装配再执行,因此语句执行一次实际所需的时间与机器的软硬件环境密切相关。所以所谓的算法分析并非精确统计算法实际执行所需时间,而是针对算法中语句的执行次数做出估计,从中得到算法执行时间的信息。

当问题规模无限大时,我们会发现 f(n) / n^3 之比是一个不等于零的常数,即f(n) 和 n^3的数量级(Order of
Magnitude)相同,或者说f(n) 和 n^3同阶。

在这里,我们用"O"表示数量级,则算法的时间复杂度T(n) = O(f(n)) = O(n^3);

一般情况下,算法中的基本语句重复执行次数是问题规模n的某个函数f(n),我们把算法的时间量度记为T(n) = O(f(n))
,它表示随问题规模n的增大,算法执行时间的增长率和f(n)的增长率相同,称作算法的渐进时间复杂度,简称时间复杂度(Time Complexity)

对于某些问题的算法,其基本语句的频度不仅仅与问题的规模相关,还依赖于其他因素,因此有时会对算法有最好、最坏以及平均时间复杂度的评价。

我们将算法在最好情况下的时间复杂度称为最好时间复杂度,指的是算法计算量可能达到的最小值。

算法在最坏情况下的时间复杂度我们称为最坏时间复杂度,指的是算法计算量可能达到的最大值;

算法的平均时间复杂度是指算法在所有可能的情况下,按照输入实例以等概率出现时,算法计算量的加权平均值。

在很多情况下,算法的平均复杂度难以确定,因此,通常只讨论在最坏情况下的时间复杂度,即分析在最坏情况下,算法执行时间的上界。

空间复杂度

关于算法的存储空间需求,类似于时间复杂度,我们采用渐进空间复杂度(Space Complexity)作为算法所需存储空间的度量,简称空间复杂度。

空间复杂度也是关于问题规模n的函数,记作:S(n) = O(f(n))

对于输入数据所占的具体存储量取决于问题本身,与算法无关,因此,我们只需要分析该算法在实现时所需要的辅助空间就可以了。

例如:

// 算法一 该算法只需要借助一个辅助变量t,因此空间复杂度为O(1)
for (i =0; i<n/2; i++){t = a[i];a[i] = a[n-i-1];a[n-i-1] = t;
}// 算法二 该算法需要借助辅助数组b[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.5 个人小结(不定期更新)

1.5.1 时间复杂度与空间复杂度的计算

对于时间复杂度与空间复杂度的计算,要牢记我们计算的最终结果是要得到一个数量级。

正因为计算的结果为数量级,因此实际上对于简单的复杂度计算问题,我们并不需要真正的算出具体的函数,而是可以通过观察直接得到结果。

例如前文中的算法:

for(i = 1; i<=n; i++){  // 频度为 n + 1for(j = 1; j<=n; j++){ // 频度为 n*(n+1)c[i][j] = 0; // 频度为 n^2for(k = 1; k<=n; k++){ // 频度为 n^2 * (n + 1)c[i][j] = c[i][j]+a[i][k]*b[k][j]; // 频度为 n^3}}
}

显然,该算法使用了3层for循环,且每个for循环执行的次数等于n,因此该算法的时间复杂度为O(n^3)。

再例如

for(i = 1; i<=1000; i++){a[i] += 1
}

显然,该算法与问题规模n无关,for循环执行的次数始终等于1000,是一个常数,而常数的数量级为1,因此该算法的时间复杂度为O(1)

🙌至此全篇结束,如果觉得对你有帮助的话,不妨点赞、收藏加关注吧!😘❤️❤️❤️

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/795025.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中国电子学会(CEIT)2021年09月真题C语言软件编程等级考试三级(含详细解析答案)

中国电子学会(CEIT)考评中心历届真题(含解析答案) C语言软件编程等级考试三级 2021年09月 编程题五道 总分:100分一、菲波那契数列(20分) 菲波那契数列是指这样的数列:数列的第一个和第二个数都为1,接下来每个数都等于前面2个数之和。给出一个正整数a,要求菲波…

深度剖析:网络安全中的红蓝对抗策略

红蓝对抗 红蓝对抗服务方案 在蓝队服务中&#xff0c;作为攻击方将开展对目标资产的模拟入侵&#xff0c;寻找攻击路径&#xff0c;发现安全漏洞和隐患。除获取目标系统的关键信息&#xff08;包括但不限于资产信息、重要业务数据、代码或管理员账号等&#xff09;外&#x…

9(10)-3-CSS 定位

个人主页&#xff1a;学习前端的小z 个人专栏&#xff1a;HTML5和CSS3悦读 本专栏旨在分享记录每日学习的前端知识和学习笔记的归纳总结&#xff0c;欢迎大家在评论区交流讨论&#xff01; 文章目录 CSS 定位1 定位组成2 定位模式3 边偏移4 静态定位 static5 相对定位 relative…

如何在iPhone上恢复永久删除的照片?

2007 年&#xff0c;Apple Inc. 推出了这款震撼人心的智能手机&#xff0c;后来被称为 iPhone。您会惊讶地发现&#xff0c;迄今为止&#xff0c;Apple Inc. 已售罄 7 亿台 iPhone 设备。根据 2023 年 8 月的一项调查数据&#xff0c;95% 的智能手机利润都落入了苹果公司的口袋…

ubuntu同步网络时间

安装ntpdate sudo apt-get update sudo apt-get install ntpdate设置系统时间与网络时间同步 sudo ntpdate cn.pool.ntp.org设置时区亚洲上海 sudo cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime设置时间为24小时制 echo "LC_TIMEen_DK.UTF-8" >>/…

Django--方法

path() 方法 一个路由配置模块就是一个urlpatterns列表&#xff0c;列表的每个元素都是一项path&#xff0c;每一项path都是以path()的形式存在。 path()方法可以接收4个参数&#xff0c;其中前2个是必须的&#xff1a;route和view&#xff0c;以及2个可选的参数&#xff1a;k…

跨平台的组播测试工具mping、udp_sender及udp_reciver的源码及使用教程

文章目录 1.前言2.mping工具编译3.mping工具使用3.1 参数说明3.1 组播播发&#xff08;-s&#xff09;3.1 组播播发&#xff08;-r&#xff09;3.3 Linux下mping测试 4.Linux组播udp_sender及udp_reciver使用4.1 udp_sender源码4.1 udp_reciver源码4.3 编译方法4.4 测试使用4.4…

android11 SystemUI入門之KeyguardPatternView解析

view层级树为&#xff1a; 被包含在 keyguard_host_view.xml中 。 <?xml version"1.0" encoding"utf-8"?> <!-- This is the host view that generally contains two sub views: the widget viewand the security view. --> <com.andro…

并发编程01-深入理解Java并发/线程等待/通知机制

为什么我们要学习并发编程&#xff1f; 最直白的原因&#xff0c;因为面试需要&#xff0c;我们来看看美团和阿里对 Java 岗位的 JD&#xff1a; 从上面两大互联网公司的招聘需求可以看到&#xff0c; 大厂的 Java 岗的并发编程能力属于标配。 而在非大厂的公司&#xff0c; 并…

16_USART串口发送和接收数据

USART串口发送和接收数据 USART串口发送和接收数据 USART串口发送和接收数据 主函数 #include "stm32f10x.h" // Device header #include "Delay.h" #include "LED.h" #include "Key.h" #include "stdint.h&q…

Linux mattrib命令教程:如何管理MS-DOS文件的属性(附实例详解和注意事项)

Linux mattrib命令介绍 mattrib 是一个用于更改MS-DOS文件属性标志的命令。它可以添加属性标志到一个MS-DOS文件&#xff08;使用 操作符&#xff09;或者移除属性标志&#xff08;使用 - 操作符&#xff09;。 Linux mattrib命令适用的Linux版本 mattrib 命令在大多数Linu…

【算法】寻找数组中心下标

题目 给定一个非空数组&#xff0c;找到一个元素&#xff0c;该元素左侧元素和等于其右侧元素和&#xff0c;返回该元素下标。 如果没有则返回-1&#xff0c;有多个则返回最左侧一个。 原理 1、双指针 定义两个变量&#xff0c;一个为从左侧累加的和 leftSum 0&#xff0c…

前端分页和后端分页

分页一般是前端分页还是后端分页 分页可以在前端或后端进行&#xff0c;具体取决于项目的需求和实现方式。以下是前端分页和后端分页的一些特点和适用场景&#xff1a; 前端分页&#xff1a; 特点&#xff1a;前端分页是指在前端&#xff08;浏览器端&#xff09;对数据进行分…

Ubuntu22.04中基于Qt开发Android App

文章目录 前言在Ubuntu22.04中配置开发环境案例测试参考 前言 使用Qt开发手机应用程序是一种高效且灵活的选择。Qt作为一个跨平台的开发框架&#xff0c;为开发者提供了统一的开发体验和丰富的功能库。首先&#xff0c;Qt的跨平台性让开发者可以使用相同的代码库在不同的操作系…

Error: TF_DENORMALIZED_QUATERNION: Ignoring transform forchild_frame_id

问题 运行程序出现&#xff1a; Error: TF_DENORMALIZED_QUATERNION: Ignoring transform for child_frame_id “odom” from authority “unknown_publisher” because of an invalid quaternion in the transform (0.0 0.0 0.0 0.707) 主要是四元数没有归一化 Eigen::Quatern…

【PostgreSQL】技术传承:使用Docker快速部署PostgreSQL数据库

前言 PostgreSQL的重要贡献者Simon Riggs因一起坠机事故不幸离世。Simon Riggs是英国著名的软件与服务领导者&#xff0c;也是PostgreSQL的主要开发者和贡献者。事故发生在英国当地时间3月26日13:41分&#xff0c;当时他驾驶的私人通用航空Cirrus SR22飞机在英国达克斯福德机场…

java——文件上传

一、文件上传——简介 文件上传的简介&#xff1a;文件上传是指将本地计算机中的文件传输到网络上的服务器或另一台计算机上的过程。在 Web 开发中&#xff0c;文件上传通常指的是将用户通过 Web 页面提交的文件&#xff08;如图像、文档、音频、视频等&#xff09;传输到服务器…

数学专题2 -最大公约数和最小公倍数

最大公约数和最小公倍数 1. 基础概念 1.1 质数的定义 质数(Prime Number)是一个重要的数学概念,它的定义如下: 如果一个大于1的自然数只有1和它本身两个因数,那么这个数就被称为质数(或素数)。 换句话说,对于一个质数 p p p,它满足以下条件: p p p 是一个大于1的自然数;如…

设计模式总结-原型设计模式

原型设计模式 模式动机模式定义模式结构模式分析深拷贝和浅拷贝原型模式实例与解析实例一&#xff1a;邮件复制&#xff08;浅克隆&#xff09;实例二&#xff1a;邮件复制&#xff08;深克隆&#xff09; 模式动机 在面向对象系统中&#xff0c;使用原型模式来复制一个对象自…

MySQL 50 道查询题汇总,足以巩固大部分查询(附带数据准备SQL、题型分析、演示、50道题的完整SQL)

目录 MySQL 50 道查询题&#xff0c;足以巩固大部分查询数据准备&#xff1a;创建表sql添加表数据sql 50道查询题目汇总01 - 05 题&#xff1a;1、查询 “01” 语文成绩比 “02” 数学成绩高的学生的信息及课程分数2、查询 "01语文课程"比"02数学课程"成绩…