绪论
文章目录
- 绪论
- 1. 什么是数据结构
- 2. 基本概念
- 数据结构的四类基本结构(逻辑结构)
- 存储结构
- 顺序存储和链式存储比较分析
- 3. 算法
- 概念
- 特征
- 优点(也是要求)
- 算法效率的度量
- 概念
- 时间复杂度
- 空间复杂度(了解)
1. 什么是数据结构
数据结构是一门研究数据的逻辑结构和物理结构
以及它们之间关系的学科,也是计算机科学的一个重要分支。
数据结构的目的是为了更高效地存储和处理数据
,从而提高计算机的性能和功能。
2. 基本概念
数据结构有以下几个基本概念:
-
数据
:数据是对客观事物的符号表示,在计算机科学中,是指所有能够输入到计算机中并被计算机程序处理的符号的总称。
-
数据元素
:数据元素是数据的基本单位,在计算机程序中通常作为一个整体进行考虑和处理。一个数据元素可以由若干个数据项组成,数据项是数据不可分割的最小单位。
-
数据对象
:数据对象是性质相同的数据元素的集合,是数据的一个子集。
-
数据类型
:数据类型是一个值的集合和定义在这个值集上的一组操作的总称。
-
数据类型分为原子类型和结构类型
原子类型是不可再分解的基本类型,如整型、字符型、布尔型等;
结构类型是由若干个类型组成的复合类型,如数组、集合等。
-
-
抽象数据类型
:抽象数据类型(Abstract Data Type,
ADT
)是指一个数学模型和定义在该模型上的一组操作。抽象数据类型体现了数据抽象的思想,即把数据的逻辑结构和操作与具体实现相分离,只暴露出必要的接口,隐藏内部细节。抽象数据类型可以用以下格式描述:
ADT 抽象数据类型名{
数据对象:<数据对象的定义>
数据关系:<数据关系的定义>
基本操作:<基本操作的定义>
操作名(<参数表>):操作说明
初始条件:<初始条件>
操作结果:<操作结果>
...
} ADT 抽象数据类型名
-
多型数据类型
:多型数据类型是指数据元素的类型不确定的数据结构,也就是说,一个多型数据类型的变量可以存储不同类型的数据元素。例如,链表、栈、队列、树、图等都是多型数据类型,因为它们的节点可以存储任意类型的数据。
相反,非多型数据类型是指数据元素的类型固定的数据结构,也就是说,一个非多型数据类型的变量只能存储一种类型的数据元素。
数据结构的四类基本结构(逻辑结构)
数据结构的四类基本结构
是指数据元素之间的逻辑关系,即数据元素之间存在什么样的关系。
根据数据元素之间关系的不同特性,通常有以下四种基本结构:
集合结构
:数据元素之间除了属于同一个集合外,没有其他关系。例如,一个班级的学生就是一个集合。线性结构
:数据元素之间存在一对一的关系。例如,线性表、栈、队列、串等都是线性结构。树形结构
:数据元素之间存在一对多的关系。例如,树、二叉树、森林等都是树形结构。图形结构
:数据元素之间存在多对多的关系。例如,图、网、有向图等都是图形结构。
图解
存储结构
存储结构是指数据的逻辑结构在计算机中的存储方式
,也称为物理结构
。它研究的是数据元素的表示和元素之间关系的表示,即数据元素在存储器上的排列方式。
存储结构主要有以下四种:
顺序存储结构
:是利用数据元素在存储器中的相对位置来表示数据元素之间的逻辑顺序。顺序存储结构是把数据元素放在地址连续的存储单元中,程序设计中使用数组类型来实现。链式存储结构
:是利用结点中指针来表示数据元素之间的关系。链式存储结构不要求数据元素在物理上相邻,而是通过指针链接起来,程序设计中使用指针类型来实现。索引存储结构
:是在存储数据元素的同时还增加了一个索引表。索引表中的每一项包括关键字和地址,关键字是能够唯一标识一个数据元素的数据项,地址是指示数据元素的存储地址或者存储区域的首地址。散列存储结构
:也称为哈希存储,这种存储方式将数据元素存储在一个连续的区域,每一个数据元素的具体存储位置是根据该数据的关键字值,通过散列(哈希)函数直接计算出来的。
顺序存储结构
链式存储结构
顺序存储和链式存储比较分析
顺序存储和链式存储
是两种常见的数据结构的存储方式,它们各有优缺点,适用于不同的场景。下面是两种存储方式的比较分析:
- 顺序存储是指
把数据元素放在地址连续的存储单元
中,可以利用数组来实现。链式存储是指把数据元素放在任意的存储单元
中,通过指针来表示数据元素之间的关系,可以利用结构体或者类
来实现。 - 顺序存储的
优点
是:存储密度大,空间利用率高,支持随机访问,查找操作方便。顺序存储的缺点
是:需要事先确定存储空间的大小,扩容或缩容比较麻烦,插入或删除操作需要移动大量的元素,效率低。 - 链式存储的
优点
是:不需要事先确定存储空间的大小,扩容或缩容比较灵活,插入或删除操作只需要修改指针,效率高。链式存储的缺点
是:存储密度小,空间利用率低,不支持随机访问,查找操作需要遍历整个链表,效率低。 - 一般来说,如果数据结构的长度变化不大,且主要操作是查找,则适合使用顺序存储;如果数据结构的长度变化较大,且主要操作是插入或删除,则适合使用链式存储。
3. 算法
概念
算法是指解决特定问题的一种方法或者一个过程,是一系列清晰的指令,可以用计算机语言来实现。
特征
算法具有以下特征:
- 输入:算法有外部提供的量作为输入,这些量表示问题的初始状态和条件。
- 输出:算法至少有一个输出,这些量表示问题的解决方案或结果。
- 确定性:算法的每条指令必须是无歧义的,即在任何情况下,只有唯一的一条执行路径。
- 有限性:算法的执行时间和执行次数必须是有限的,即算法必须在有限步骤内终止。
- 可行性:算法中执行的任何计算步骤都是可以被分解为基本的可执行的操作步骤,即每个计算步骤都可以在有限时间内完成(也称之为有效性)。
优点(也是要求)
算法可以应用于各种领域,如数学、计算机科学、工程、物理、生物等。不同的领域可能有不同的算法设计方法和评价标准。
一般来说,一个好的算法应该具有以下优点:
- 正确性:算法能够正确地解决问题,即对于任何合法的输入,都能得到正确的输出。
- 可读性:算法能够用清晰、简洁、规范的语言来描述,便于人们理解和修改。
- 健壮性:算法能够处理异常或错误的输入,不会产生不可预期的结果。
- 效率:算法能够在较短的时间内完成任务,即占用较少的时间资源。
- 空间:算法能够在较小的空间内完成任务,即占用较少的存储资源。
算法效率的度量
概念
算法效率的度量是指评估算法在执行过程中所消耗的时间和空间资源的方法。一般来说,更关注算法的时间效率,也就是算法的时间复杂度。
时间复杂度
时间复杂度是指算法执行时间与问题规模之间的关系,用大O符号表示,记为T (n) = O(f (n)),其中n是问题规模,f (n)是一个函数,表示算法执行时间随n的增长而增长的量级。
为了计算算法的时间复杂度,我们需要遵循以下步骤:
- 找出算法中的基本操作,通常是最内层循环的循环体。
- 计算基本操作的执行次数的数量级,忽略低次幂和高次幂的系数,只保留最高次幂。
- 用大O符号表示算法的时间性能,将基本操作执行次数的数量级放入大O符号中。
在计算算法时间复杂度时,还需要注意以下几个规则:
加法规则
:如果算法的两个部分时间复杂度分别为T1 (n) = O(f (n))和T2 (n) = O(g (n)),则T1 (n) + T2 (n) = O(max(f (n), g (n)))。乘法规则
:如果算法的两个部分时间复杂度分别为T1 (n) = O(f (n))和T2 (n) = O(g (n)),则T1 (n) * T2 (n) = O(f (n) * g (n))。常数规则
:如果g (n) = O(f (n)),则O(f (n)) + O(g (n)) = O(f (n));O(C * f (n)) = O(f (n)),其中C是一个正常数。
常见的时间复杂度有以下几种:
常数阶O(1)
,表示算法执行时间与问题规模无关,如简单的赋值或输入输出语句。对数阶O(log n)
,表示算法执行时间与问题规模的对数成正比,如二分查找或折半插入排序。线性阶O(n)
,表示算法执行时间与问题规模成正比,如顺序查找或冒泡排序。线性对数阶O(n log n)
,表示算法执行时间与问题规模和问题规模的对数的乘积成正比,如快速排序或归并排序。平方阶O(n^2)
,表示算法执行时间与问题规模的平方成正比,如选择排序或插入排序。立方阶O(n^3)
,表示算法执行时间与问题规模的立方成正比,如矩阵乘法或冒泡排序改进版。指数阶O(2^n)
,表示算法执行时间与2的问题规模次方成正比,如汉诺塔问题或幂集问题。阶乘阶O(n!)
,表示算法执行时间与问题规模的阶乘成正比,如旅行商问题或全排列问题。
一般来说,随着问题规模n的不断增大,上述时间复杂度不断增大,算法的执行效率越低。常见的算法时间复杂度由小到大依次为:O(1) < O(log n) < O(n) < O(n log n) < O(n^2) < O(n^3) < O(2^n) < O(n!) < O(n^n)。
O(1)
对数阶O(log n)
线性阶O(n)
线性对数阶O(n log n)
平方阶O(n^2)
空间复杂度(了解)
空间复杂度是指算法在执行过程中所占用的存储空间与问题规模之间的关系,用大O符号表示,记为S (n) = O(f (n)),其中n是问题规模,f (n)是一个函数,表示算法占用空间随n的增长而增长的量级。
为了计算算法的空间复杂度,需要遵循以下步骤:
- 找出算法中的辅助空间,通常是指除了输入数据和输出结果所占用的空间之外的额外空间,如临时变量、递归栈等。
- 计算辅助空间的大小的数量级,忽略低次幂和高次幂的系数,只保留最高次幂。
- 用大O符号表示算法的空间性能,将辅助空间大小的数量级放入大O符号中。
在计算算法空间复杂度时,还需要注意以下几个规则:
- 加法规则:如果算法的两个部分空间复杂度分别为S1 (n) = O(f (n))和S2 (n) = O(g (n)),则S1 (n) + S2 (n) = O(max(f (n), g (n)))。
- 乘法规则:如果算法的两个部分空间复杂度分别为S1 (n) = O(f (n))和S2 (n) = O(g (n)),则S1 (n) * S2 (n) = O(f (n) * g (n))。
- 常数规则:如果g (n) = O(f (n)),则O(f (n)) + O(g (n)) = O(f (n));O(C * f (n)) = O(f (n)),其中C是一个正常数。
常见的空间复杂度有以下几种:
- 常数阶O(1),表示算法占用空间与问题规模无关,如简单的赋值或输入输出语句。
- 线性阶O(n),表示算法占用空间与问题规模成正比,如动态数组或链表。
- 平方阶O(n^2),表示算法占用空间与问题规模的平方成正比,如二维数组或矩阵。
- 指数阶O(2^n),表示算法占用空间与2的问题规模次方成正比,如递归求解汉诺塔问题或幂集问题。
一般来说,随着问题规模n的不断增大,上述空间复杂度不断增大,算法的执行效率越低。常见的算法空间复杂度由小到大依次为:O(1) < O(n) < O(n^2) < O(2^n)