数据结构——绪论
1.1数据结构的研究内容
数据结构是一门研究如何合理地组织数据、高效地处理数据,并它们进行有效的处理,设计出高效的算法的一门学科。
1.2基本术语和概念
1.2.1 数据、 数据元素、 数据项和数据对象
我的理解:
数据:数字化的信息集合,包含日常见到的文字,图片,图像,视频等
数据元素:用来描述现实事物的一条数据
数据项:组成数据元素的各个项
数据对象:同一类型的数据元素集合
标准术语:
数据 (Data) 是客观事物的符号表示,用文字符号、数字符号以及其他规定符号对客观现实世界的事物的一种抽象信息描述
数据元素(Data Element) 是数据的基本单位,用来表示一个事物的一组数据
数据项 (Data Item) 是组成数据元素的、有独立含义的、不可分割的最小单位。
数据对象 (Data Object) 是性质相同的数据元素的集合,是数据的一个子集。
1.2.2 数据结构
我的理解:
数据结构就是通过数据元素之间存在的联系,将数据组织起来,形成某种结构。
数据结构包括存储结构和逻辑结构
存储结构就是数据在内存地址中如何存储,既数据的存储地址是否连续
逻辑结构是脱离于存储结构的,只关注在逻辑上的组织结构
标准术语:
数据结构 (Data Structure) 是相互之间存在一种或多种特定关系的数据元素的集合。换句话
说,数据结构是带 ”结构" 的数据元素的集合, “结构” 就是指数据元素之间存在的关系。
-
逻辑结构:数据的逻辑结构是从逻辑关系上描述数据,它与数据的存储无关,是独立千计算机的。因此,
数据的逻辑结构可以看作是从具体问题抽象出来的数学模型。
数据的逻辑结构有两个要素:一是数据元素;二是关系。数据元素的含义如前所述,关系是
指数据元素间的逻辑关系。根据数据元素之间关系的不同特性, 通常有四类基本结构:
集合结构:(数据元素之间无关系,只是同在一个集合)
线性结构:(数据元素存在一对一的逻辑关系,比如数组,栈,队列,广义表)
树形结构:(数据元素存在一对多的逻辑关系,代表是二叉树)
图结构: (数据元素存在多对多的逻辑关系,分为有向图和无向图)
-
存储结构:数据对象在计算机中的存储表示称为数据的存储结构,也称为物理结构。把数据对象存储到
计算机时,通常要求既要存储各数据元素的数据,又要存储数据元素之间的逻辑关系,数据元素
在计算机内用一个结点来表示。数据元素在计算机中有两种基本的存储结构,分别是顺序存储结
构和链式存储结构。
1.2.3 数据类型和抽象数据类型
我的理解:
数据类型:具有相同性质的数据集合
抽象数据类型:用来描述现实事物的一个抽象数据模型
标准术语:
数据类型:是一组性质相同的值的集合,以及定义在这个集合上的一组操作的总称
抽象数据类型:通常由用户定义,用于表示实际应用问题的数据模型,一般由基本数据类型或其他已定义的抽象数据模型及定义在该模型上的一组操作组成(类似于java的类)
1.3 抽象数据类型的表示与实现
下面以复数为例, 给出一个完整的抽象数据类型的定义、 表示和实现。
(l) 定义部分:
ADT Complex {
数据对象:D={el, e2 I el, e2ER,R 是实数集}
数据关系: S={<el,e2>1el 是复数的实部, e2 是复数的虚部}
基本操作:
Creat (&C, x, y)
操作结果:构造复数C, 其实部和虚部分别被赋以参数x和y的值。
GetReal(C)
初始条件:复数C已存在。
操作结果:返回复数C的实部值。
Getimag (C)
初始条件:复数C已存在。
操作结果:返回复数c的虚部值。
Add( Cl,C2)
初始条件:Cl, C2 是复数。
操作结果:返回两个复数 Cl和 C2 的和。
Sub(Cl,C2)
初始条件:Cl, C2 是复数。
操作结果:返回两个复数 Cl 和 C2 的差。
} ADT Complex
(2) 表示部分:
typedef struct{
float Realpart; //实部
float Imagepart; //虚部
}Complex;
(3) 实现部分:
void Create(&Complex C, float x, float y) {//构造一个复数
C.Realpart=x;
C.Imagepart=y;
}
float GetReal(Complex C) { //取复数C=x+yi的实部
return C.Realpart;
}
float Getimag (Complex C) { //取复数C=x+yi的虚部
return C.Imagepart;
}
Complex Add(Complex Cl, Complex C2) { //求两个复数Cl和C2的和sum
Complex sum;
sum.Realpart=Cl.Realpart+C2.Realpart;
sum.Imagepart=Cl.Imagepart+C2.Imagepart;
return sum;
}
Complex Sub(Complex Cl, Complex C2) { //求两个复数Cl和C2的差difference
Complex difference;
difference.Realpart=Cl.Realpart-C2.Realpart;
difference.Imagepart=Cl.Imagepart-C2.Imagepart;
return difference;
}
1.4 算法和算法分析
数据结构和算法相辅相成,程序=数据结构+算法
1.4.1 算法的定义及特性
算法 (Algorithm) 是为了解决某类问题而规定的一个有限长的操作序列。
一个算法必须满足以下五个重要特性。
我的理解:
输入:一个算法应该有0个或多个输入的数据,对数据进行处理
输出:返回1个或多个结果,算法必须要有结果,否则无意义
有穷性:算法不能是无休止的计算,应该具备有限次计算
确定性:算法的每一步都是确定的,无异议的
可行性:算法的每一个序列都应该可行
标准术语:
(1)有穷性:一个算法必须总是在执行有穷步后结束,且每一步都必须在有穷时间内完成。
(2) 确定性:对于每种情况下所应执行的操作,在算法中都有确切的规定,不会产生二义性,
使算法的执行者或阅读者都能明确其含义及如何执行。
(3) 可行性:算法中的所有操作都可以通过已经实现的基本操作运算执行有限次来实现。
(4) 输入:一个算法有零个或多个输入。当用函数描述算法时,输入往往是通过形参表示的,
在它们被调用时,从主调函数获得输入值。
(5) 输出:一个算法有一个或多个输出,它们是算法进行信息加工后得到的结果,无输出的
算法没有任何意义。当用函数描述算法时,输出多用返回值或引用类型的形参表示。
1.4.2 评价算法优劣的基本标准
一个算法的优劣应该从以下几方面来评价。
(1)正确性。在合理的数据输入下,能够在有限的运行时间内得到正确的结果。
(2) 可读性。一个好的算法,首先应便千人们理解和相互交流 , 其次才是机器可执行性。可
读性强的算法有助于人们对算法的理解,而难懂的算法易千隐藏错误,且难千调试和修改。
(3) 健壮性。当输入的数据非法时,好的算法能适当地做出正确反应或进行相应处理,而不
会产生一些莫名其妙的输出结果。
(4) 高效性。高效性包括时间和空间两个方面。时间高效是指算法设计合理,执行效率高,
可以用时间复杂度来度量;空间高效是指算法占用存储容量合理,可以用空间复杂度来度量。时间复杂度和空间复杂度是衡量算法的两个主要指标。
1.4.3 算法的时问复杂度
1. 问题规模和语句频度
问题规模 是算法求解问题输入量的多少,是问题大小的本质表示,一般用整数n表示。问题规模n对不
同的问题含义不同,例如,在排序运算中n为参加排序的记录数,在矩阵运算中n为矩阵的阶数,在多项式运算中
n为多项式的项数,在集合运算中n为集合中元素的个数,在树的有关运算中n为树的结点个数,在图的有关运算中n为图的顶点数或边数。显然,n越大算法的执行时间越长。
一个算法的执行时间大致上等于其所有语句执行时间的总和, 而语句的执行时间则为该条语句的重复执行次数
和执行一次所需时间的乘积。
一条语句的重复执行次数称作语句频度(FrequencyCount)。
设每条语句执行一次所需的时间均是单位时间, 则一个算法的执行时间可用该算法中所有语句频度之和来度量。
[例] 求两个n阶矩阵的乘积算法。
for(i=l;i<=n;i++){ //频度为 n+1
for (j=l; j<=n; j++){ //频度为 n*(n+1)
c[i] [j]=O; //频度为 n^2
for(k=l;k<=n;k++){ //频度为 n^2 * (n+1)
c[i][j]=c[i][j]+a[i][k]*b[k][j]; //频度为n^3
}
}
}
该算法中所有语句频度之和, 是矩阵阶数n的函数, 用f{n)表示。
换句话说, 上例算法的执行时间与 f(n )成正比。
f(n)=2n3+3n2+2n+1
2.算法的时间复杂度定义
一般情况下, 算法中基本语句重复执行的次数是问题规模n的某个函数f(n), 算法的时间量度记作
T(n) = O(f(n))
它表示随问题规模n的增大, 算法执行时间的增长率 和 f(n)的增长率相同, 称做算法的
渐近时间复杂度, 简称时间复杂度(TimeComplexity)。
如何计算语句频度和估算时间复杂度
https://blog.csdn.net/qq_45702990/article/details/107552565
1.4.4 算法的空问复杂度
关于算法的存储空间需求,类似于算法的时间复杂度,我们采用渐近空间复杂度(Space
Complexity)作为算法所需存储空间的扯度,简称空间复杂度,它也是问题规模n的函数,
记作:
S(n) = O(f (n))
简单来说就是
对一个算法在运行过程中临时占用的存储空间大小的量度,一般也作为问题规模n的函数,以数量级形式给出
记作:S(n) = O(f (n))
如果算法执行所需要的临时空间不随着某个变量n的大小而变化,即此算法空间复杂度为一个常量,可表示为 O(1)
[ 例 ]
int i = 1;
int j = 2;
++i;
j++;
int m = i + j;
xity)作为算法所需存储空间的扯度,简称空间复杂度,它也是问题规模n的函数,
记作:
S(n) = O(f (n))
简单来说就是
对一个算法在运行过程中临时占用的存储空间大小的量度,一般也作为问题规模n的函数,以数量级形式给出
记作:S(n) = O(f (n))
如果算法执行所需要的临时空间不随着某个变量n的大小而变化,即此算法空间复杂度为一个常量,可表示为 O(1)
[ 例 ]
int i = 1;
int j = 2;
++i;
j++;
int m = i + j;
代码中的 i、j、m 所分配的空间都不随着处理数据量变化,因此它的空间复杂度 S(n) = O(1)