数据结构与算法——基本概念与术语
概述
数据、数据元素、数据对象
数据(data)是对客观事物的符号表示,在计算机科学中是指所有能输入到计算机中并被计算机程序处理的程序的总称。
数据元素(data element)是数据的基本单位,在计算机程序中通常作为一个整体进行考虑和处理。一个数据元素可由若干个数据项(data item)组成。数据项是数据的不可分割的最小单位。
数据对象(data object)是性质相同的数据元素的集合,是数据的一个子集。
如此表,这两张表都是数据,除此之外,图片、音频、视频都是数据的一种。
数据对象是性质相同数据元素的集合。学生表可以看成是一个数据对象,同理,成绩表也是一个数据对象。
两张表的每一行都可以看作是一个数据元素。
每一行的每一列就是一个数据项(即学号、姓名、科目、成绩、年龄就是一个个的数据项)。
数据结构
数据结构是相互之间存在一种或多种特定关系的数据元素的集合。数据结构就是研究数据在程序中的组织方式。
数据结构类型有如下几种:
1.集合(set)结构中的数据元素之间除了“同属于一个集合”的关系外,别无其他关系。
2.线性结构(linear structure)结构中的数据元素之间存在一个对一个的关系。
3.树形结构(tree structure)结构中的数据元素存在一个对多个的关系。
4.图形结构(graphic structure)结构中的数据元素之间存在多个对多个的关系。
物理结构/存储结构
数据结构在计算机中的表示(又称映像)称为数据的物理结构,又称存储结构。它包含数据元素的表示和关系的表示。
数据结构之间的关系在计算机中有两种不同的表示方法:顺序映像和非顺序映像,并由此得到两种不同的存储结构,顺序存储结构和链式存储结构。顺序存储结构中,线性表的逻辑顺序和物理顺序总是一致的。但在链式存储结构中,线性表的逻辑顺序和物理顺序一般是不同的。
算法
程序=数据结构+算法
说完数据结构,再来看一下算法
算法是对特定问题求解步骤的一种描述,他是指令的有限序列,其中每一条指令表示一个或多个操作(算法解决问题的步骤)
算法的五个特性:
1.有穷性 一个算法必须对任何合法输入都在执行有穷步后结束,且每一步都必须在有穷时间内完成。
2.确定性 算法的每一条指令必须有确切的含义,读者在阅读时不会产生二义性。并且,在任何条件下,算法只能由惟一的一条执行路径,即对于相同的输入只能得到相同的输出。
3.可行性 算法中描述的操作都是可以通过已经实现的基本运算执行有限次来实现。
4.输入 一个算法有零个或多个输入。
5.输出 一个算法有一个或多个输出。
算法设计的要求
一个“好”的算法应考虑达到以下目标,以下目标也是一个算法的评价标准
1.正确性、2.可读性、3.健壮性、4.效率与低存储量需求
其中,最重要衡量算法优劣的就是复杂度。
复杂度
复杂度包括时间复杂度和空间复杂度。时间复杂度就是指算法的执行次数,并非执行时间。空间复杂度就是算法运行过程中要占用的最大内存。随着计算机内存容量的逐步扩大,相对来说,现在更加看重算法的时间复杂度.
时间复杂度
一个算法是由控制结构(顺序、分支和循环3种)和原操作(指固有数据类型的操作)构成的,时间复杂度取决于两者的综合结果。
一般情况下,算法的基本操作重复执行的次数是问题规模n的某个函数f(n),算法的时间度量记作T(n)=O(f(n)),它表示随问题规模n的增大,算法执行时间的增加率和f(n)的增长率相同,称做算法的渐进时间复杂度,简称时间复杂度。可以理解为“O”来表示数量级的概念。
多数情况下它是指最深层循环内的语句的原操作,它的执行次数和包含它的语句的频度相同。语句的频度指的是该语句重复执行的次数。
例:
void test(int n) { for(int i = 0; i < n; i++) { // 循环次数为 n printf("Hello, World!\n"); // 循环体时间复杂度为 O(1) } }
for循环的循环次数是n,所以printf("Hello, World!\n"); 的频度是 n,则程序段的时间复杂度是 T(n)=O(n)
void test(int n) { for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) printf("Hello, World!\n"); }
这是二重循环的函数,外层循环为n次,内层循环为n次,所以printf("Hello, World!\n"); 的频度是 n*n.则程序段的时间复杂度为T(n)=O(n²) 。
void test(int n) { // 第一部分时间复杂度为 O(n^2) for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) printf("Hello, World!\n"); // 第二部分时间复杂度为 O(n) for(int j = 0; j < n; j++) printf("Hello, World!\n"); }
此时时间复杂度为O(n^2+n)。因为当n极大的时候,n的值可以忽略不计,n^2+n的值可以近似为n^2的值,所有时间复杂度为O(n^2)