数据是信息的载体,能够被计算机识别、存储和加工处理,数据包括文字、表格、图像等。
信息是数据的内涵,即数据所表达的意义。
数据项是具有独立意义的不可分割的最小标识单位(表格中的学号)。
数据的基本单位是数据元素(有时称为结点、记录等)
数据对象是具有相同类型的数据元素的集合(学生的信息类型相同),因为所有数据元素类型相同时处理起来更加方便,所以在数据结构中除特别指定外数据通常都是数据对象 。
数据结构是相互之间存在一种或多种特定关系的数据元素的集合。这些数据元素不是孤立存在的,而是有着某种关系,这种关系构成了某种结构。
数据元素之间的逻辑关系的整体称为数据的逻辑结构,这里的逻辑关系主要指数据元素之间的相邻关系(课程中只考虑是否相邻,相邻则有关系,否则没有关系)。它与数据的存储无关,是独立于计算机的,是从具体问题抽象出来的数学模型。分为下列4类基本结构:
前驱和后继的概念:以下表为例,刘英在李斌和张山中间,李斌是刘英的前驱,张山是刘英的后继,王实是第一个数据元素,所以没有前驱,陈功是最后一个元素,所以没有后继。
(1)线性结构(线性表、栈、队列、字串,数组…… )
元素之间为一对一的线性关系,第一个元素无直接前驱,最后一个元素无直接后继,其余元素都有一个直接前驱和直接后继。
.
(2)非线性结构(树、堆、图(网络),…… )
元素之间为一对多或多对多的非线性关系,每个元素有多个直接前驱或多个直接后继。
逻辑结构、存储结构和运算三者之间的关系:
数据的存储方式是灵活多样的,存储结构是逻辑结构在计算机存储器中的映像,必须依赖于计算机
1、顺序存储结构
①顺序存储结构采用一组连续的存储单元存放所有的数据元素(数组)。
②逻辑上相邻的元素的存储单元也相邻,也就是说,顺序存储结构将数据的逻辑结构直接映射到存储结构。
③顺序存储结构的主要优点是节省存储空间。因为分配给数据的存储单元用于存放元素值,元素之间逻辑关系的表示没有占用额外的存储空间。用这种方法来存储线性结构的数据元素时,可实现对各数据元素的随机存取。即顺序存储结构具有随机存取特性。
①链式存储结构中的每个存储单元称为“结点”,结点包含一个数据域和一个指针域;
②数据域存放数据元素信息;指针域存放后继结点地址;
③链式存储结构中每个结点单独存储,无需占用一整块存储空间。但为了表示结点之间的关系,给每个结点附加指针字段,用于存放相邻结点的存储地址。
④由于链表中每个链结点中仅包含一个指针域,故称这样的链表为线性链表或单链表。
⑤链式存储结构的优点是便于修改,在进行插入、删除运算时,只需修改结点的指针域,不必移动结点,缺点是存储空间的利用效率低,因为分配给数据元素的存储单元中有一部分被用来存放结点之间的逻辑关系了。另外,由于逻辑上相邻的结点在存储器中不一定相邻,所以链式存储在线性结构中不能对结点进行随机存取。
总结:在线性结构存储中,顺序存储结构多用来查找元素,链式存储多用来插入和删除元素
C/C++语言中允许使用typedef关键字为一个数据类型指定一个别名,例如:typedef char ElemType;该语句将char类型与ElemType等同起来。这样做有两个好处:
①方便程序调试,例如,将上述语句改为typedef int ElemType,则程序中所有ElemType都改为int类型了。(一改全改)
②可以简化代码。
1、算法的特点:
有限性:一个算法必须总是(对任何合法的输入值)在执行有限步之后结束,且每一步都可在有限时间内完成。
确定性:算法中每一条指令必须有确切的含义,不会产生二义性。
可行性:算法中每一条运算都必须是基本的,就是说原则上都能精确地执行,甚至人们用笔和纸做有限次运算就能完成。
输入性:一个算法有零个或多个输入。
输出性:一个算法有一个或多个输出。
典型的例子:
描述1是一个死循环,违反了算法的有限性特性。
描述2出现除零错误,违反了算法的可行性特性。
2、C++中可以用引用来进行值回传
上面的程序执行时发现输出结果为0,b对应的形参为s,Sum1执行后s=55,但s并没有回传给b。在C语言中可以用传指针方式来实现形参的回传,但增加了函数的复杂性。C++语言中增加了引用型参数的概念,引用型参数名前需加上&,表示这样的形参在执行后会将结果回传给对应的实参。如下:
1、时间复杂度
一个算法花费的时间与算法中语句的执行次数成正比例,一个算法中的语句执行次数称为语句频度或时间频度。记为T(n), n称为问题的规模,当n不断变化时,时间频度T(n)也会不断变化。
①一个没有循环的算法中基本运算次数与问题规模n无关,记作O(1),也称作常数阶。
.
②一个只有一重循环的算法中基本运算次数与问题规模n的增长呈线性增大关系,记作O(n),也称线性阶。
.
③其余常用的还有平方阶O(n2)、立方阶O(n3)、对数阶O(log2n)、指数阶O(2n)等等。
.
④可通过for循环来判断,一个for循环是O(n),两个是O(n2),以此类推(while循环不行)。
解法1:从求算法中所有语句的频度来分析算法时间复杂度。
语句①的执行频度为n+1(注意i语句②的执行频度为n(n+1)
语句③的执行频度为n2
语句④的执行频度为n2(n+1)
语句⑤的执行频度为n3
所以T(n)=2n3+3n2+2n+1=O(n3)
解法2:从算法中基本运算的频度来分析算法时间复杂度。
基本运算是语句⑤
其频度为n3
所以T(n)=n3=O(n3)
while循环经典例子:
void func(int n)
{ int i=1,k=100;
while (i<=n)
{ k++;
i+=2;
}
}
假设while循环执行的次数为m,i以每次加2的幅度递增,当跳出循环时则有:i=1+2m<=n,所以时间复杂度为T(n)=m≤(n-1)/2=O(n)
各种不同数量级对应的值存在着如下关系:
O(1)
2、空间复杂度
①一个算法的存储量包括形参所占空间和临时变量所占空间等。
②对算法进行存储空间分析时,只考察临时变量所占空间。
为什么算法占用的空间只考虑临时空间,而不必考虑形参的空间呢?这是因为形参的空间会在调用该算法的算法中考虑,也就是说形参的空间已经在max函数中分配。
maxfun算法中为b数组分配了相应的内存空间,其空间复杂度为O(n),如果在max算法中再考虑形参a的空间,这样就重复计算了占用的空间。实际上,在C/C++语言中,maxfun调用max时,max的形参a只是一个指向实参b数组的指针,形参a只分配一个地址大小的空间,并非另外分配5个整型单元的空间。
总结:
时间复杂度:评估执行程序所需的时间。可以估算出程序对处理器的使用程度。
空间复杂度:评估执行程序所需的存储空间。可以估算出程序对计算机内存的使用程度。
了解更多IT资讯,关注我吧!