NO.1数据结构绪论|数据结构|逻辑结构|物理结构|算法|算法的度量
数据结构
相关概念
- 【数据】 客观事物的符号表示, 可以将计算机中存储的一切都看成是数据。
- 【数据元素】 数据的基本单位, 在计算机中通常作为一个整体进行考虑, 这个概念 根据具体的问题要具体界定, 概念外延可大可小。
- 【数据项】 是数据不可分割的最小单位。 一个数据元素可由若干个数据项组成。
- 【数据对象】 性质相同的数据元素的集合。
- 【逻辑结构】 数据元素之间的逻辑关系。 这个关系与计算机无关, 仅限于人的思维层面。
- 【存储结构】 逻辑结构在计算机中的表示, 也称物理结构。
- 【数据结构】 数据结构是逻辑结构和物理结构的统称。 有时数据结构可以看成是逻 辑结构的称谓
逻辑结构
数据的逻辑结构是指数据元素之间的逻辑关系。 这与计算机无关, 仅限于人的思维层面。
★ 数据的逻辑结构分为线性和非线性
【线性】 线性表、 栈、 队列、 串、 数组、 广义表
【非线性】 集合、 树、 图
★ 数据元素之间的关系
【线性结构】 数据元素之间只存在一对一的关系, 除第一个元素外,所有元 素都有唯一前驱; 除最后一个元素外, 所有元素都有唯一后继。
【树形结构】 数据元素之间存在一对多的关系。
【图状结构或网状结构】 数据元素之间存在多对多的关系。
物理结构
数据的存储结构是用计算机语言实现的逻辑结构
数据的存储结构主要有: 顺序存储、 链式存储、 索引存储和散列存储
★ 顺序存储
把逻辑上相邻的元素存储在物理位置上也相邻的存储单元内 元素之间的元素关系由存储单元的邻接关系来体系。
【优点】 可以实现随机存取, 每个元素占用最少的存储空间。
【缺点】 只能使用相邻的一整块存储单元, 因此可能产生较多的外部碎片。
★ 链式存储
不要求把逻辑上相邻的元素存储在物理位置上也相邻的存储单元内 借助指示元素存储地址的指针来表示元素之间的逻辑关系。
【优点】 不会出现碎片现象, 充分利用所有存储单元
【缺点】 每个元素因存储指针而占用额外的存储空间, 并且只能实现顺序存取
★ 索引存储
在存储元素信息的同时, 建立附加索引表 索引表中的每一项称为索引项, 索引项的一般形式是(关键字, 地址)
【优点】 检索速度快
【缺点】 索引表占用额外存储空间, 增删数据时也需要花费时间更改索引表
★ 散列存储
根据元素关键字直接计算出该元素存储地址, 又称为: 哈希(Hash) 存
储。
【优点】 检索、 增加、 删减结点操作很快
【缺点】 如果散列函数不好可能出现元素存储单元的冲突, 而解决冲突会增加时间和空间开销。
★ 数据的运算
施加在数据上的运算包括运算的定义和实现。
运算的定义是针对逻辑结构的, 指出运算的功能。
运算的实现是针对存储结构的, 指出运算的具体操作步。
数据结构包含逻辑结构, 存储结构和数据的运算; 而只需要抽象数据类型(ADT)即可定义一个完整的数据结构。
算法
定义
- 【数据结构】
a) 就是研究数据的存储方式
b) 把现实中大量而复杂的问题以特定的数据类型(单个数据存储)和特定的 存储结构(个体的关系) 保存到内存中 - 【算法】
a) 在此基础上为实现某个功能(查找, 删除, 排序等) 而进行的操作
数据结构用于解决存储数据, 算法对存储数据的操作。
五大特征
- 有穷性: 必须执行有限步后结束
- 确定性: 每一步必须有确切定义
- 可行性: 任何步骤都可被分解为基本的可执行操作, 每个操作都能在有限时间内完成
- 输入: 算法必须有零个或多个输入
- 输出: 算法必须有一个或多个输出
四大目标
正确性:算法可以正确的解决问题
可读性:算法程序应易读,好理解
健壮性:可以应对非法数据,处理好边界条件
效率与低存储量需求:优秀的时间复杂度和空间复杂度
算法的度量
★ 空间复杂度
定义: 算法的空间复杂度即该算法所耗费的存储空间
原地工作: 我们在算法中需要一个数组来传存放输入的 n 个数据, 另外还需要一些与 n 无关 的常量的空间来存放算法需要的其他数据, 那么该算法的空间复杂度为 O(n)。 如果算法需要所耗费的存储空间并不随输入数据的变化而变化, 那么该算法的空间 复杂度为 O(1)。 我们称之为算法原地工作
★ 时间复杂度
定义 : 以算法中基本操作重复执行的次数(简称为频度) 作为算法的时间度量。 一般不必要精确计算出算法的时间复杂度, 只要大致计算出相应的数量级即可, 如 O(1)、 O(n)等
计算过程
- 确定规模 n: 通常在形参中会给出问题规模 n
- 计算频度 T(n): 通常以算法中的基本运算(若有循环, 循环中最深层的语句为 基本运算) 为核心, 求出其执行的次数
- 用大 O 表示: 只保留 T(n)的最高阶项, 如果这个最高阶项的序数不为 1, 忽略这个序数
O(log(n!)) = O(nlogn)
求时间复杂度题型技巧归纳:
对于多层循环的题目
- 如果最外层是非线性变化, 例如指数变化, 那么只能采用定义法求时间复杂度;
- 如果最外层是线性变化, 那么定义法和简便法都可以求时间复杂度;
求时间复杂度时, 需要关注的地方:
- 循环的特点, 是线性变化还是非线性变化;
- 循环退出的条件;
- 循环体内执行的语句;
例题
1
- 找出基本操作,确定规模 n
i. 找出基本操作。 多数情况下取最深层循环内的语句所描述的操作作为基本操作。 显然题目中++j; 语句 i+=2; 语句都可以作为基本操作
ii. 确定规模。 由循环条件 i 可以知道, 循环次数和参数 n 有关, 即规模为 n. - 计算出 n 的函数 f(n)
问题规模 n 确定以后, 循环结束与否与 i 有关。 i 的初值为 1, 每次自增 2 假设 i 自增 k 次后循环结束, 则 i 最后的值为1 + 2 * k += n
解得
k=(n-1)/2
, 即f(n)=(n-1)/2
, 最高次项为n/2
, 时间复杂度为 O(n).
2
- 找出基本操作,确定规模 n
i. 找出基本操作。 显然题目中++i; 语句 s=s+i; 语句都可以作为基本操作
ii. 确定规模。 由循环条件 s < n 可以知道, 循环次数和参数 n 有关,即规模为 n. - 计算出 n 的函数 f(n) i 和 s 的初值都为 0, 假设循环执行 m 次结束, 则
s1=1,s2=1+2=3,s3=1+2+3=6,…,sm=m(m+1)2 s_{1} = 1,s_{2}=1+2=3,s_{3}=1+2+3=6,\dots,s_{m}=\frac{m(m+1)}{2} s1=1,s2=1+2=3,s3=1+2+3=6,…,sm=2m(m+1)
最后的值为m(m+1)/2=n
, 由求根公式得: 解m=-1+√8n+1
, 即f(n)=-1-√ 8n+1
,时间复杂度为 T(n) = O(n1/2n^{1/2}n1/2)