数据结构和算法——数据结构和算法的概念

文章目录

  • 数据结构
  • 算法
    • 算法分析
      • 时间复杂度
      • 空间复杂度

数据结构

数据是信息的载体,是计算机程序加工的原料,数据元素是数据的基本单位,数据项是构成数据元素的最小单位。数据对象是具有相同性质的数据元素的集合(强调的是数据元素性质的相同)。

数据结构和算法——数据结构和算法的概念_第1张图片

数据结构是指相互之间存在一种或多种特定关系的数据元素的集合(强调的是数据元素之间的关系)。数据结构的三要素是逻辑结构、存储结构和数据运算。

数据结构和算法——数据结构和算法的概念_第2张图片

算法

算法是为求解一个问题需要遵循的、被清楚指定的简单指令的集合。一个算法具有以下五个特性:

数据结构和算法——数据结构和算法的概念_第3张图片

一个算法的设计取决于所选定的逻辑结构,而算法的实现依赖于所采用的存储结构。

算法分析

一旦给定一个算法并且确认其是正确的,那么重要的一步就是对这个算法进行算法分析,算法分析主要考虑算法的效率,算法效率包含以下两方面:

  • 时间效率:指算法所消耗的时间,用时间复杂度来表示。
  • 空间效率:指算法执行过程中所消耗的存储空间。用空间复杂度来表示。

时间复杂度

一个算法的运行的时间大致可以等于计算机执行算法指令的时间( t t t)与指令执行次数( n n n)的乘积。
T ( n ) = ∑ i = 1 n t i × n T(n)=\sum_{i=1}^{n} t_i\times n T(n)=i=1nti×n

由于每个指令执行的时间由计算机的硬件和软件条件决定,和算法本身没有关系,因此可以将每个指令执行的时间可以看作一个单位时间,那么讨论算法执行时间的问题就变成了讨论算法执行频度的问题:

T ( n ) = ∑ i = 1 n n T(n)=\sum_{i=1}^{n} n T(n)=i=1nn

下面分析一下选择排序算法的执行频度:

public static void selectionSort(int []data){
    for (int i = 0; i < data.length-1; i++) { //n次
        int minIndex=i; //n-1次
        for (int j = i+1; j < data.length; j++) { //n(n-1)/2次
            if (data[j]<data[minIndex]){ //n(n-2)/2次
                minIndex=j; //n(n-2)/2次
            }
        }
        int temp=data[i]; //n-1次
        data[i]=data[minIndex]; //n-1次
        data[minIndex]=temp; //n-1次
    }
}

所以选择排序的执行频度为:
T ( n ) = 3 n 2 ÷ 2 + 5 n ÷ 2 − 4 T(n)=3n^2\div2+5n\div2-4 T(n)=3n2÷2+5n÷24

但是这一过程也相当的繁琐并且结果难以比较,由公式
lim ⁡ x → ∞ a n x n + a n − 1 x n − 1 + ⋯ + a 1 x + a 0 b m x m + b m − 1 x m − 1 + ⋯ + b 1 x + b 0 = { a n b m , n = m 0 , n < m ∞ , n > m \lim\limits_{x\to\infty}\frac{a_nx^n+a_{n-1}x^{n-1}+\cdots+a_1x+a_0}{b_mx^m+b_{m-1}x^{m-1}+\cdots+b_1x+b_0}=\begin{cases}\frac{a_n}{b_m},n=m\\0,nm\end{cases} xlimbmxm+bm1xm1++b1x+b0anxn+an1xn1++a1x+a0= bman,n=m0,n<m,n>m
可知,如果存在一个函数 f ( n ) f(n) f(n),使 lim ⁡ n → ∞ T ( n ) f ( n ) = C ( C ≠ 0 ) \lim\limits_{n \to \infty}\frac{T(n)}{f(n)}=C(C\ne0) nlimf(n)T(n)=C(C=0),那么 f ( n ) f(n) f(n) T ( n ) T(n) T(n)就是同阶的,记作 T ( n ) = O ( f ( n ) ) T(n)=O(f(n)) T(n)=O(f(n)) O ( f ( n ) ) O(f(n)) O(f(n))就称为算法的时间复杂度。那么上述选择排序的时间复杂度就为 O ( n 2 ) O(n²) O(n2)。也就是说在寻找算法频度时不需要找出所有语句执行的频度,只需要找出对算法频度贡献最大的语句即可。此外,输入数据的性质会影响算法的执行频度,在这种情况下将算法的时间复杂度分为三种:

  • 最坏时间复杂度:输入数据的性质使算法的执行频度很高。
  • 平均时间复杂度:输入数据的性质使算法的执行频度很平均。
  • 最好时间复杂度:输入数据的性质使算法的执行频度很低。

但一般只考虑最坏时间复杂度,以保证算法的运行时间不会比它更长。在计算程序的时间复杂度时,有以下两条规则:

  • 加法原则: 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)))
  • 乘法原则: T ( n ) = T 1 ( n ) × T 2 ( n ) = O ( f ( n ) ) × O ( g ( n ) ) = O ( f ( n ) × O g ( n ) ) T(n)=T_1(n)\times T_2(n)=O(f(n))\times O(g(n))=O(f(n)\times Og(n)) T(n)=T1(n)×T2(n)=O(f(n))×O(g(n))=O(f(n)×Og(n))

常见时间复杂度的关系为:
O ( 1 ) < O ( l o g 2 n ) < O ( n ) < O ( n l o g 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)

空间复杂度

与时间复杂度类似,算法的空间复杂度记作:
S ( n ) = O ( f ( n ) ) S(n)=O(f(n)) S(n)=O(f(n))

它包括算法本身要占据的空间以及使用的辅助空间。在计算空间复杂度时只需要计算辅助空间即可,比如上述的选择排序算,它仅需要一个临时变量作为辅助空间,所以它的空间复杂度为 O ( 1 ) O(1) O(1),当算法的空间复杂度为 O ( 1 ) O(1) O(1)时称它在原地工作。注意,当函数递归调用时,要考虑每一次递归使用的辅助空间。

你可能感兴趣的:(数据结构与算法,算法,数据结构,排序算法)