//# 如何使用数据结构
//## 数组和链表
//## 堆栈和队列
//## 线性表和数组ADT
//## 字符串和广义表
//## 树
//## 集合和搜索
//## 搜索树
//## 跳表和散列表
//## 图
为何使用数据结构
程序=算法+数据结构
什么是数据结构
数据(data)
- 数值数据(numerical data)
包括一些整数、实数或复数,主要用于工程计算、科学计算、商务处理等。 - 非数值数据(non-numerical data)
包括字符、文字、图形、图像、语音、表格等。这类数据的特点是景大,而且往往有着复杂的内在联系。
数据元素(data element):组成数据的成分数据。
数据项(data item):组成数据元素的成分数据。
数据结构(data structure)
数据的逻辑结构
逻辑结构(logical structure):对数据元素间的逻辑关系的描述。
数据的基本逻辑结构
- 集合结构(set)
- 线性结构(linear)
- 树形结构(tree)
- 图状结构(graph)
数据的基本结构关系
- 线性结构(linear structure)
- 线性结构(linear)
- 非线性结构(non-linear structure):
- 集合结构(set)
- 树形结构(tree)
- 图状结构(graph)
数据的存储结构
存储结构(storage structure):数据结构的实现形式,是其在计算机内的表示;数据在计算机内的组织方式,逻辑数据的存储映像。计算机内存是由有限个存储单元组成的一个连续存储空间,这些存储单元或名是字节编址的或字编址的。从存储器角度肴,内存中是一堆二进制数据,机器指令可以解释其为指令、整数、字符、布尔数等,数据结构的算法可以解释其为具有某种结构的数据。
数据的基本存储结构
- 顺序(sequential)存储结构(或称连续(contiguous))存储结构:需要一整块连续的存储空间,并把逻辑上相关的数据元素依次存储在该连续的存储区中。
- 链接存储结构:为了在计算机中存储一个元素,除了需要存放该元素本身的信息外,还需要存放与该元素相关的其他元素的位置信息。
- 结点(node):元素本身的信息与该元素相关的其他元素的位置信息的组合。
- 链(link):关于与元素相关的其他结点的位置信息。
- 其他数据存储结构
- 索引(index)
- 散列(hash)
数据结构分类(根据算法)
算法(algorithm)
- 创建运算:创建一个数据结构。
- 清除运算:删除数据结构中的全部元素。
- 插入运算:在数据结构中插入一个新元索。
- 删除运算:将数据结构中的某个指定元素删除。
- 搜索运算:在数据结构中搜索满足一定条件的元素。
- 更新运算:修改数据结构中某个指定元素的值。
- 访问运算:访问数据结构中某个元素。
- 遍历运算:按照某种次序,系统地访问数据结构的各元索,使得每个元素恰好被访问一次。
数据结构分类
- 静态数据结构(static data structure):一旦创建,其结构不会发生改变的数据结构;没有定义了插入和删除运算的数据结构。
- 动态数据结构(dynamic data structure):定义了插入和删除运算的数据结构。
数据抽象/抽象数据类型
- 抽象(abstraction):抽取共同的和本质的内容,忽略非本质的细节。
目的:降低问题求解的难度,提高程序的可靠性
抽象机制
- 数据抽象(data abstraction):分开考虑数据元素间的逻辑关系和数据元素间的存储关系(数据在计算机内的具体表示)。
- 过程抽象(procedual abstraction):分开考虑算法原理(运算的定义)与算法实现(实现运算的具体方法)。
封装,模块与接口
- 封装(encapsulation):数据和操纵数据的运算结合在一起的机制。
- 信息隐蔽(information hiding):采用封装这种设计数据结构或程序的策略。
目的:对使用者隐藏了数据结构以及程序的实现结构。 - 模块(module): 内部数据和操纵数据的运算组合。
黑盒:采用封装和信息隐藏的模块。 - 接口(interface):模块中明确定义的访问方法;模块内部数据只能经过这个访问方法被外部访问。
客户(client):调用模块的其他模块/使用模块的其他程序。
数据类型和抽象数据类型
- 数据结构的规范(specification):逻辑结构和运算的定义;规范是实现的准则和依据;“做什么”
- 数据结构的实现(implementation):数据的存储表示和运算算法的描述;“怎么做”
抽象数据类型
数据结构与算法
算法:求解一类问题的任意一种特殊的方法;对特定问题的求救步骤的一种描述;指令的有限序列。
算法的特征(5个)
- 输入(input):算法有零个或多个输入。
- 输出(output):算法至少产生一个输出。
- 确定性(definite):算法的每一条指令都有确切的定义,没有二义性。
- 能行性(effective):算法的每一条指令都足够基本,它们可以通过执行有限次己经实现的基本运算来实现。
- 有穷性(terminative):算法总能在执行有限步之后终止。
算法的复杂度
算法的复杂度=时间的复杂度+空间的复杂度
时间复杂度
时间复杂度(time complexity):程序运行从开始到结束所需的时间。
- 特定的实例(instance):程序的某一次运行。
- 实例的特征(characteristics):程序的某一次运行中的元素个数。
- 实例的规模(size):程序的输入量(有时也设计输出量)。
时间复杂度的分析方法(2种)
-
事前分析(priori analysis):在排除程序运行环境 的因素后再来讨论算法的时间效率;算法运行时间的一种事前估计。
程序步(program step):在语法上或语义上有意义的程序段;程序段的执行时间与问题实例的特征无关。 -
事后测试(posterori testing):测试一个程序在所选择的输入数掘 下运行时实际需要的时间。
时间复杂度的分类(3种)
- 算法的最好情况(best case)
- 算法的最坏情况(worst case)
- 算法时间代价的平均情况(average case)
渐进时间复杂度/时间复杂度
- 算法的渐近时间复杂度(asymptotic complexity):使用大O记号表示的算法的时间复杂度;O(1)表示常数计算时间,即算法只需执行有限个程序步。
- 常见的渐近时间复杂度按从小到大顺序排列为:O(1) <O(log2 n)<O(n)<O(n log2 n)<O(n2) < O(n3)<O(2n),
空间复杂度
空间复杂度=固定部分+可变部分
程序的空间复杂度(space complexity):程序运行从开始到结束所需的存储量。
程序运行所需的存储空间包括两部分:
- 固定部分(fixed space requirement):与所处理数据的大小和个数无关,或者说与问题的实例的特征无关。包括程序代码、常量、简单变量、定长成分的结构变量所占的空间。
- 可变部分(variable space requirement):与算法在某次执行中处理的特定数据的大小和规模有关。包括数据元索所占的空间, 以及算法执行所需的额外空间,如递归栈所用的空间。
注意:空间复杂度一般按最坏情况来分析。