写在前面
Hello大家好, 我是【麟-小白】,一位软件工程专业的学生,喜好计算机知识。希望大家能够一起学习进步呀!本人是一名在读大学生,专业水平有限,如发现错误或不足之处,请多多指正!谢谢大家!!!
如果小哥哥小姐姐们对我的文章感兴趣,请不要吝啬你们的小手,多多点赞加关注呀!❤❤❤ 爱你们!!!
目录
1.什么是数据结构?
1.1 定义
数据结构是一门研究非数值计算的程序设计问题中计算机的操作对象以及它们之间的关系和操作等的学科。
一般来说,用计算机解决一个具体问题时,大致需要经过以下几个步骤:
- 首先要从具体问题抽象出一个适当的数学模型,然后设计一个解此数学模型的算法,最后编出程序,进行测试、调整直至得到最终解答。
- 寻求数学模型的实质是分析问题,从中提取操作的对象,并找出这些操作对象之间含有的关系,然后用数学的语言加以描述。
2. 基本概念和术语
2.1 数据、数据元素、数据项和数据对象
- 数据:数据是对客观事物的符号表示,在计算机科学中是指所有能输入到计算机中并被计算机程序处理的符号的总称。
- 数据元素:数据元素是数据的基本单位,在计算机程序中通常作为一个整体进行考虑和处理。一个数据元素可由若干个数据项组成。数据项是数据不可分割的最小单位。
- 数据对象:数据对象是性质相同的数据元素的集合,是数据的一个子集。
- 数据元素和数据对象的区别:数据元素与数据的关系:是集合的个体。数据对象与数据的关系:是集合的子集。
- 位:在计算机中表示信息的最小单位是二进制数的一位,叫做位(bit)。
- 元素:在计算机中,我们可以用一个由若干位组合起来形成的一个位串表示一个数据元素(如用1个字长的位串表示一个整数,用8位二进制数表示一个字符等),通常称这个位串为元素或节点。
- 数据域:当数据元素由若干数据项组成时,位串中对应于各个数据项的子位串称为数据域。
2.2 数据结构
- 数据结构:数据结构是相互之间存在一种或多种特定关系的数据元素的集合,或者说,数据结构是带结构的数据元素的集合。
- 结构:在任何问题中,数据元素都不是孤立存在的,而是在它们之间存在着某种关系,这种数据元素相互之间的关系成为结构。
- 逻辑结构:结构定义中的“关系”描述的是数据元素之间的逻辑关系,因此又称为数据的逻辑结构。
- 存储结构:数据结构在计算机中的表示(又称映像)称为数据结构的物理结构,又称存储结构。
- 逻辑结构与存储结构的关系:存储结构是逻辑关系的映像;逻辑结构是数据结构的抽象,存储结构是数据结构的实现;两者综合起来建立了数据元素之间的结构关系。
- 逻辑结构的种类:
划分方法一:
线性结构:有且仅有一个开始和终端结点,并且所有结点都最多只有一个直接前趋和一个直接后继。例如:线性表、栈、队列、串。
非线性结构:一个结点可能有多个直接前趋和直接后继。例如:树、图。
划分方法二:------四类基本逻辑结构:
根据元素之间关系的不同特性,通常有下列四类基本结构:
集合:结构中的数据元素之间除了“同属于一个集合”的关系外,别无其他关系。
线性结构:结构中的数据元素之间存在一个对一个的关系。
树形结构:结构中的数据元素之间存在一个对多个的关系。
图状结构或网状结构:结构中的数据元素之间存在多个对多个的关系。
- 四种基本的存储结构:
- 顺序存储结构:用一组连续的存储单元依次存储数据元素,数据元素之间的逻辑关系由元素的存储位置来表示。C语言中用数组来实现顺序存储结构。
- 链式存储结构:用一组任意的存储单元存储数据元素,数据元素之间的逻辑关系用指针来表示。C语言中用指针来表示链式存储结构。
- 索引存储结构:在存储结点信息的同时,还建立附加的索引表,索引表中的每一项称为一个索引项。索引的一般形式是:(关键字, 地址)。关键字是能唯一标识一个结点的那些数据项,若每个结点在索引表中都有一个索引项,则该索引表称之为稠密索引;若一组结点在索引表中只对应一个索引项,则该索引表称之为稀疏索引。
- 散列存储结构:根据结点的关键字直接计算出该结点的存储地址。
2.3 数据类型和抽象数据类型
- 数据类型:一个值的集合和定义在这个值集上的一组操作的总称。
- 抽象数据类型:指一个数学模型以及定义在该模型上的一组操作。它由用户定义,从问题抽象出数据模型(逻辑结构),还包括定义在数据模型上的一组抽象运算(相关操作),不考虑计算机内的具体存储结构与运算的具体实现方法。
- 抽象数据类型的形式定义:
- 原子类型:原子类型的值是不可分解的,如C语言中的基本类型(整型、实型、字符型和枚举类型)、指针类型和空类型。
- 结构类型:结构类型的值是由若干成分按某种结构组成的,因此是可以分解的,并且它的成分可以是非结构的,也可以是结构的。
- 固定聚合类型:属该类型的变量,其值由确定数目的成分按某种结构组成。例如,复数是由两个实数依确定的次序关系构成。
- 可变聚合类型:和固定聚合类型相比,构成可变聚合类型“值”的成分和数目不确定。例如,可定义一个“有序整数序列”的抽象数据类型,其中序列的长度是可变的。
- 多形数据类型:指其值的成分不确定的数据类型。
- 抽象数据类型的表示与实现:
抽象数据类型可通过固有数据类型来表示和实现,即利用处理器中已存在的数据类型来说明新的结构,用已经实现的操作组合新的操作。
3. 算法与算法分析
3.1 算法的定义
- 对特定问题求解方法和步骤的一种描述,它是指令的有限序列。其中每个指令表示一个或多个操作。简而言之,算法就是解决问题的方法和步骤。
3.2 算法的描述
- 自然语言:英文、中文。
- 流程图:传统流程图、NS流程图。
- 伪代码:类语言:类C语言。
- 程序代码:C语言程序、JAVA语言程序……
3.3 算法与程序
- 算法是解决问题的一种方法或一个过程,考虑如何将输入转换成输出,一个问题可以有多种算法。
- 程序是用某种程序设计语言对算法的具体实现
- 程序=数据结构+算法
- 数据结构通过算法实现操作
- 算法根据数据结构设计程序
3.4 算法特性
一个算法必须具备以下五个重要特性:
- 有穷性:一个算法必须总是在执行有穷步之后结束,且每一步都在有穷时间内完成。
- 确定性:算法中的每一条指令必须有确切的含义,没有二义性,在任何情况下,只有唯一的一条执行路径,即对于相同的输入只能得到相同的输出,
- 可行性:算法是可执行的,算法描述的操作可以通过已经实现的基本操作执行有限次来实现。
- 输入:一个算法有零个或多个输入,
- 输出:一个算法有一个或多个输出。
3.5算法设计的要求
- 正确性:算法满足问题要求,能正确解决问题。
算法转化为程序后要注意:
1.程序中不含语法错误;
2.程序对于几组输入数据能够得出满足要求的结果;
3.程序对于精心选择的典型、苛刻而带有刁难性的几组输入数据能够得出满足要求的结果;
4.对于一切合法的输入数据都能产生满足要求的结果。
通常以第三次意义上的正确性作为衡量一个算法是否合格的标准。
- 可读性:算法主要是为了人的阅读和交流,其次才是计算机执行,因此算法应该易于人的理解;另一方面,晦涩难读的算法易于隐藏较多错误而难以调试。
- 健壮性:指当输入非法数据时,算法恰当的做出反应或进行相应处理,而不是产生莫名其妙的输出结果。处理出错的方法不应中断程序的执行而应是返回一个表示出错或错误性质的值,以便在更高的抽象层次上进行处理,
- 高效性:要求花费尽量少的时间和尽量低的存储需求。
3.6 算法分析
- 一个好的算法首先要具备正确性,然后是健壮性、可读性,在几个方面都满足的情况下,主要考虑算法的效率,通过算法的效率高低来评判不同算法的优劣程度。
- 算法效率有以下两个方面来考虑:
- ①时间效率:指的是算法所耗费的时间。
- ②空间效率:指的是算法执行过程中所耗费的存储空间。
- 时间效率和空间效率有时候是矛盾的。
- 算法时间效率的度量:算法时间效率可以用依据该算法编制的程序在计算机上执行所消耗的时间来度量。有以下两种方法:
- ①事后统计:将算法实现,测算其时间开销和空间开销。缺点:编写程序实现算法将花费较多的时间和精力;所得实验结果依赖于计算机的软硬件等环境因素,掩盖算法本身的优劣。
- ②事前分析:对算法所消耗资源的一种估算方法。
- 事前分析方法:
- 一个算法的运行时间是指一个算法在计算机上运行所消耗的时间大致可以等于计算机执行一种简单的操作(如赋值、比较、移动等)所需的时间与算法中进行的简单操作次数乘积。
- 算法运行时间 = 一个简单操作所需的时间 × 简单操作次数
- 也即算法中每条语句的执行时间之和。
- 算法时间 = ∑每条语句的执行次数 × 该语句执行一次所需的时间
- 每条语句的执行次数又称语句频度。
- 每条语句执行一次所需的时间,一般是随机器而异的。取决于机器的指令性能、速度以及变异的代码质量。是由机器本身软硬件环境决定的,它与算法无关。
- 所以我们可假设执行每条语句所需的时间均为单位时间,此时对算法的运行时间的讨论就可转化为讨论该算法中所有语句的执行次数,即频度之和了。这就可以独立与不同机器的软硬件环境来分析算法的时间性能了
- 例如:两个n × n矩阵相乘的算法可描述为:
- 我们把算法所消耗的时间定义为该算法中每条语句的频度之和,则上述算法的时间消耗 T(n)为:T(n)=2n³+3n²+2n+1
- 算法时间复杂度的渐进表示法:
- 为了便于比较不同算法的时间效率,我们仅比较它们的数量级
- 例如两个不同的算法时间消耗分别是:
- T1(n)=10n² 与 T2(n)=5n³ 其实这不太好比较
- 若有某个辅助函数 f(n),使得n趋近于无穷大时,T(n) / f(n)的极限值为不等于0的常数,则称 f(n) 是T(n)的同数量级函数。记作T(n)=O(f(n)),称O(f(n))为算法的渐进时间复杂度,简称时间复杂度。
- 对于求解矩阵相乘问题,算法耗费时间.
T(n)=2n³+3n²+2n+1
n→∞时,T(n)/n³→2,这表示n充分大时,T(n)与n³是同阶或同数量级,引入大“O”记号,则T(n)可记作:T(n)=0(n³)
这就是求解矩阵相乘问题的算法的渐进时间复杂度。- 一般情况下,不必计算所有操作的执行次数,而只考虑算法基本操作执行的次数,它是问题规模n的某个函数,用T(n)表示。
- 算法中基本语句的执行次数是问题规模n的某个函数 f(n) ,算法的时间量度记作:T(n) = O(f(n))。
- 它表示随n的增大,算法执行的时间的增长率和f(n)的增长率相同,称渐进时间复杂度。
- 数学符号“O”的定义为:若T(n)和f(n)是定义在正整数集合上的两个函数,则T(n) = O(f(n))表示存在正的常数C和n0,使得当n≥n0时都满足0≤T(n)≤C(f(n))。
- 什么是基本语句呢?
- 算法中重复执行次数和算法的执行时间成正比的语句。
- 对算法运行时间的贡献最大。
- 执行次数最多。
- 什么是问题规模n呢?
- n越大算法的执行时间越长。
- 排序:n为记录数。
- 矩阵:n为矩阵的阶数。
- 多项式:n为多项式的项数。
- 集合:n为元素个数。
- 树:n为树的结点个数。
- 图:n为图的定点数或边数。
- 分析算法时间复杂度的基本方法:
- 定理:
- 方法:
- 1.找出语句频度最大的那条语句作为基本语句。
- 2.计算基本语句的频度得到问题规模n的某个函数 f(n)。
- 3.取其数量级用符号“O”表示。
例如:
- 注意:有的情况下,算法中基本操作重复执行的次数还随问题的输入数据集不同而不同
- 对于复杂的算法,可以将它分成几个容易估算的部分,然后利用大O加法法则和乘法法则,计算算法的时间复杂度。
- 算法时间效率的比较:
- 当n取得很大时,指数时间算法和多项式时间算法在所需时间上非常悬殊。
- 渐进空间复杂度
- 空间复杂度:算法所需存储空间的量度。记作:S(n) = O(f(n)) ,其中n为问题的规模(或大小)。
- 算法要占据的空间包括:
- 算法本身要占据的空间,输入/输出,指令,常数,变量等。
- 算法要使用的辅助空间。
- 例如:将一维数组a中的n个数逆序存放到原数组中:
结语
本人会持续更新文章的哦!希望大家一键三连,你们的鼓励就是作者不断更新的动力