[数据结构笔记]绪论

在这里插入图片描述

基本术语

  • 数据元素是集合,由多个数据项构成。
  • 数据项是构成数据元素的不可分割的最小单位
  • 数据对象是具有相同性质的数据元素的集合(如整数集合 N N N
  • 数据结构是相互之间存在一种或多种特定关系的数据元素集合
  • 数据运算的定义是针对逻辑结构的,实现是针对存储结构的。

  • 算法是对特定问题的求解步骤的描述,是指令的有限序列
  • 算法具有五大特性(可行性、正确性、有穷性、输入、输出)
  • 正确性是指相同的输入有相同的输出
  • 有穷是有限次操作,也要求有限的时间内完成
  • 一个的算法应该考虑达到:正确性、可读性、健壮性、效率与低存储量要求

基本推论

  • 链式存储,结点的储存单元地址一定连续
  • 存储数据时,不仅要存储数据元素的值,还要存储数据元素之间的关系
  • 算法时间复杂度 O ( n 2 ) O(n^2) O(n2)表示该算法的执行时间和 n 2 n^2 n2成正比
  • 原地工作的算法所需辅助空间为常量,即 O ( 1 ) O(1) O(1)不是不需要额外空间
  • 时间复杂度排序 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(\log_2n)<O(n)<O(n\log_2n)<O(n^2)<O(n^3)<O(2^n)<O(n!)<O(n^n) O(1)<O(log2n)<O(n)<O(nlog2n)<O(n2)<O(n3)<O(2n)<O(n!)<O(nn)
  • 同一个算法,实现的语言级别越高,执行效率越低
  • 时间复杂度是指最坏情况下估算算法执行时间的一个上界

其他辨析

逻辑结构

经典划分是两类:线性结构和非线性结构

根据数据元素之间的关系来看:

名称 定义
集合 结构中的数据元素之间除同属一个集合外别无关联
线性结构 结构中的数据元素之间只存在一对一的关系
树形结构 结构中的数据元素之间存在一对多的关系
结构中的数据元素之间存在多对多的关系

集合一般是非线性结构。

有序表和顺序表和线性表

顺序表:

  • 物理空间的连续
  • 例如数组
  • 顺序表和链表是一组相对的概念。就好像顺序存储和链式存储是相对的一组概念一样。

线性表:

  • 表示的一组数据在逻辑上具有前驱和后继的关系
  • 实现可以是顺序表也可以是线性表
  • 直观特点是可以通过index访问
  • 显然kv对不是线性表

有序表:

  • 首先它是个线性表
  • 其次它的元素按某种逻辑指定的顺序排序(这意味着它的排序算法有可能需要你传入一个比较函数)

定义完整数据结构

定义完整数据结构的一定是ADT(抽象数据类型):

ADT = (D, S, P)
D: 数据对象
S: D上的关系集
P: D上的操作集

即数据、数据关系和基本运算(详见我的[CS61A]Week03笔记1

有序表属于逻辑结构

上面说了吧,有序表是线性表的一种。线性表的实现有顺序存储和链式存储。

主要是它只强调了逻辑关系,即有序。但是要说“顺序表是逻辑结构”就片面了。因为它既强调了逻辑关系,也指明了存储结构。

数据的逻辑结构独立与存储结构

这话不能反过来说。不知道逻辑结构是无法确定存储结构的。并且因为一种逻辑结构可以对应很多种物理结构,所以称之为独立。

相同的逻辑结构在不同的存储方式下的效率差异

线性表在顺序存储时的插入和删除平均时间复杂度 O ( n ) O(n) O(n),但是链式存储只要 O ( 1 ) O(1) O(1)

时间复杂度

多循环且内层循环有上界在变就用多 ∑ \sum 式子按部就班求

for(i = n - 1; i > 1; i--){
    
    
	for(j = 1; j < i; j++){
    
    
		if(A[j]>A[j+1])swap(A[j], A[j+1]);
	}
}

其中n为做正整数,则swap语句的频度在最坏的情况下为: O ( n 2 ) O(n^2) O(n2)

解:当所有元素均逆序则都每次均执行

T ( n ) = ∑ i = 2 n − 1 ∑ j = 1 i − 1 1 = ∑ i = 2 n − 1 ( i − 1 ) = ( n − 2 ) ( n − 1 ) / 2 = O ( n 2 ) T(n)=\sum_{i=2}^{n-1}\sum_{j=1}^{i-1}1=\sum_{i=2}^{n-1}(i-1)=(n-2)(n-1)/2=O(n^2) T(n)=i=2n1j=1i11=i=2n1(i1)=(n2)(n1)/2=O(n2)


for(i = 1; i <= n; i++)
	for(j = 1; j <= i; j++)
		for(k = 1; k <= j; k++)
			x++;

∑ i = 1 n ∑ j = 1 i ∑ k = 1 j 1 = ∑ i = 1 n ∑ j = 1 i j = ∑ i = 1 n i ( i + 1 ) 2 = O ( 1 6 n 3 ) = O ( n 3 ) \sum_{i=1}^{n}\sum_{j=1}^{i}\sum_{k=1}^{j}1=\sum_{i=1}^{n}\sum_{j=1}^{i}j=\sum_{i=1}^{n}\frac{i(i+1)}{2}=O(\frac16n^3)=O(n^3) i=1nj=1ik=1j1=i=1nj=1ij=i=1n2i(i+1)=O(61n3)=O(n3)


两长度分别为m和n的升序链表合成为一个长度为m+n的降序链表,最坏情况下时间复杂度为: O ( m a x ( m , n ) ) O(max(m,n)) O(max(m,n))

【说明】:考查加法规则

T ( n ) = T 1 ( n ) + T 2 ( n ) = O ( f ( n ) ) + O ( g ( n ) ) = O ( m a x ( f ( n ) , g ( n ) ) ) T(n)=T_1(n)+T_2(n)=O(f(n))+O(g(n))=O(max(f(n),g(n))) T(n)=T1(n)+T2(n)=O(f(n))+O(g(n))=O(max(f(n),g(n)))


int func(int n){
    
    
	int i = 0, sum = 0;
	while(sum < n) sum += ++i;
	return i;
}

时间复杂度为 n \sqrt{n} n

对于给定输入规模n 要找出循环次数t和n的函数关系 f ( t ) < n f(t)<n f(t)<n,随后反解

本题中循环次数t满足 ( 1 + t ) ∗ t 2 < n \frac{(1+t)*t}{2}<n 2(1+t)t<n,在n足够大时影响左侧的是二阶的 t 2 t^2 t2 t 2 < n t^2 < n t2<n,故循环次数即时间复杂度为 n \sqrt n n

总结

  1. 把握好循环次数t,找准t和输入问题规模n的关系。
  2. 递归程序一般使用公式递推,格式如下:

T ( n ) = 1 + T ( n − 1 ) = 1 + 1 + T ( n − 2 ) = . . . = n − 1 + T ( 1 ) T(n)=1+T(n-1)=1+1+T(n-2)=...=n-1+T(1) T(n)=1+T(n1)=1+1+T(n2)=...=n1+T(1)

主要就是一直化简到 T ( 1 ) T(1) T(1)常量为止。其他的常用的方法还有递归树和主方法

猜你喜欢

转载自blog.csdn.net/qq_39377889/article/details/128634422
今日推荐