数据结构学习笔记(第一章:概论)

第一章:绪论

  • 1.1 数据结构的基本概念
    • 基本概念
    • 数据结构的三要素
  • 1.2 算法和算法评价
    • 算法的基本概念
    • 算法效率的度量

1.1 数据结构的基本概念

基本概念

基本概念
数据
数据元素、数据项
数据对象、数据结构
数据类型、抽象数据类型(ADT)
代指计算机中所有能被计算机程序所识别的信息
数据元素:就像是C语言中的结构体,是数据的
基本单位,通常是作为一个整体考虑和处理
数据项:就像C语言结构体所包含的变量,
数据项数构成数据元素的不可分割的最小单位
数据结构:是一种关系,它表示的数据
元素中存在一种或多种的特定关系集合
数据对象:还有具有相同性质的数据
元素的集合,是数据的子集
  • 抽象数据类型(ADT)的定义取决于它的逻辑特性,不管计算机如何表示和实现,只要它的数学特性不变,则这其实是同一个抽象数据类型。
  • 抽象数据类型(ADT)描述了数据的逻辑结构和抽象运算,通常用(D数据对象,S数据关系,P基本操作集)这样的三元组来表示,从而构成一个完整的数据结构定义。

数据结构的三要素

1.逻辑结构:
逻辑结构分为线性结构和非线性结构,线性表是典型的线性结构。非线性结构里又含有集合,树形结构和图状结构(网状结构),集合,树和图是经典的非线性结构。

2.物理结构(数据的存储结构):
主要有顺序存储,链式存储,索引存储,散列存储(哈希Hash存储)。

  • 顺序存储:就是逻辑上应该相邻的数据元素也顺序存储在存储单元中。
  • 链式存储:就是虽然有数据元素逻辑上是相邻的,但是数据可能分散在任意存储单元中,逻辑相邻的前后数据元素依靠(地址)指针来导向。
  • 索引存储:数据可能分散在任意存储单元中,逻辑相邻的前后数据元素依靠一个索引表来导向。
  • 散列存储(哈希存储):给定一种公式,通过元素的特征用公式直接计算出该元素的存储空间。

3.数据的运算:

  • 针对逻辑结构:指运算的功能。
  • 针对存储结构:指运算的具体操作步骤

Notes:

1.逻辑结构:仅描述元素之间的逻辑关系,它可以用多种存储方式来实现。例如:栈,栈既可以才用顺序存储或者链式存储,故属于逻辑结构,有序表是指关键字有序的线性表,同样属于逻辑结构;而顺序表,哈希表,单链表则不是,因为它描述了逻辑结构了之后又将存储结构和数据运算定死了,所以不属于逻辑结构。
2. 在存储数据时,不仅要存储数据元素的值,而且要存储数据元素之间的关系。
3. 对于两种不同的数据结构,逻辑结构或物理结构有可能是相同的,比如:二叉树二叉排列树,他们的逻辑结构和物理结构完全一致,但是由于数据结构的三要素之一:“数据的运算”的原理不一样,所以这是两种不同的数据结构。
4.相同的逻辑结构,同一种运算在不同的存储方式下实现时,运算的效率有可能不一样,比如:线性表,线性表可以用顺序存储方式实现又可以用链式存储方式实现。在顺序存储方式下,在线性表中插入和删除元素,平均要移动一半的元素,时间复杂度是O(n),但是链式存储方式下,不需要移动其他元素,插入和删除的时间复杂度都仅为O(1)。

1.2 算法和算法评价

算法的基本概念

算法的基本概念
定义
程序 = 数据结构 + 算法
数据结构是要处理的信息
算法是处理信息的步骤
算法的五个特征
有穷性
可以执行完毕
算法是有穷的
程序可以无穷
确定性
确认相同的信息只有一个输出结果
可行性
可以实现它
输入
有信息输入
输出
有处理结果输出
好算法的特质
正确性
可读性
健壮性
效率和低存储容量
你的算法结果是否正确?
你的算法别人能看懂吗?
你的算法Bug多不多?
算得快不快呀,时间复杂度低不低?
占用内存大不大呀,空间复杂度多少?

算法效率的度量

1.时间复杂度
时间开销与问题规模n的关系O(f(n))
运行时间记为 T ( n ) T(n) T(n)
算法中基本操作重复的次数和问题规模n的比例函数记为 f ( n ) f(n) f(n)
T(n)=O(f(n));
2.空间复杂度
空间开销(系统开销)与问题规模n的关系

加法规则: O ( f ( n ) ) + O ( g ( n ) ) = O ( m a x ( f ( n ) , g ( n ) ) ) O(f(n))+O(g(n))=O(max(f(n),g(n))) O(f(n))+O(g(n))=O(max(f(n),g(n)))
乘法规则: O ( f ( n ) ) ∗ O ( g ( n ) ) = O ( f ( n ) ∗ g ( n ) ) O(f(n))*O(g(n))=O(f(n)*g(n)) O(f(n))O(g(n))=O(f(n)g(n))
常对幂指阶: O ( 1 ) < O ( log ⁡ 2 n ) < O ( n ) < O ( n log ⁡ 2 n ) < O ( n 2 ) < O ( n 3 ) < O ( 2 n ) < O ( n ! ) < O ( n n ) O(1)O(1)<O(log2n)<O(n)<O(nlog2n)<O(n2)<O(n3)<O(2n)<O(n!)<O(nn)

Notes:
时间复杂度的表示要注意算法执行时间的增长率和f(n)的增长率相同即可,例如O(2n)一般写成O(n)。所以时间复杂度的优劣评估更注重增长率,并且一般忽略在某一特殊数值下的比较。
时间复杂度总是考虑最坏的情况,这能保证算法的运行时间不会比它更长。
算法原地工作是指算法所需的辅助空间是常量。
同一算法,实现语言的级别越高,执行效率会越低

例题:已知两个长度分别为m和n的升序链表,若将他们合并成长度为m+n的一个降序链表,则最坏情况下的时间复杂度是?
答案:O(max(m, n))

无论两个升序链表内部是怎么样的,都要有m+n次移动才能变成一个降序链表,所以这里时间复杂度就应该直接剔除这部分。

这里的时间复杂度主要是考察的两个链表的比较部分,比较应该从每个链表中最大的数开始,也就是从后往前看

最好的情况:无疑是长度比较短的升序链表a中的第一个数还比另一个升序数列b最后一个数还大,升序链表a中的数肯定是链表中最小的,所以比较只用比较完a的长度后,就能直接将b的剩下的数直接放入。所以比较次数为min(m,n);

举个例子:像b(4,5,6,7)和a(8,9,10),首先10与7比较,10大放入序列;9与7比较,9大放入序列;8与7比较8大放入序列,这时比较短的a序列已经全部放完,剩下的另一个序列已经不需要比较了,直接从后往前一一放入即可。这时就只进行了3次比较。

最坏的情况:无疑是a,b链表都比较到剩任一列最后一个,只有最后一个数是不用比较的,所以出现了m+n-1次比较,

答案为啥是时间复杂度不是O(m+n-1)呢,因为时间复杂度的表示只需要表示增长率,所以表示是一次方即可,但是是O(n)还是O(m)呢?

这是最坏的情况所以应该选比较大得那个,所以O(max(n,m));

感想:
这篇学习笔记是我在学习王道和严蔚敏数据结构的小结,应该算是转载,而且有些不理解的地方也通过上网搜索才了解的东西。以为自己之前学得还行,结果从新复习的时候才发现真的是个渣渣。

你可能感兴趣的:(数据结构)