本文内容是自己通过对本章的学习,概括汇总知识点以及加上自己的理解而写。不会有很多的概念性定义。而是旨在对大家该章知识框架的形成提供帮助,包括对知识的复盘,并且用最通俗的语言来帮助大家理解我所认为重要的知识。
如果你是来进行系统的学习,那么本文可能只是用来拓展知识面;但如果你是在学习相关内容后,对于框架体系的建立比较模糊,以及部分知识点存在疑惑,那么本文应该非常适合你。
我们首先根据这张思维导图开启今日知识点复盘吧。
数据结构这本书主要就是研究数据结构,以及它是如何实际应用的——算法,再对算法进行一个评价,判断它的好坏。
问题:
1、逻辑结构有哪些
2、什么是存储结构,有哪些,他们的区别
3、评价好的算法的标准
4、评价顺序存储和链式存储,各有什么优缺点。
数据结构三要素包括逻辑结构、存储结构、数据的运算
其中,逻辑结构和存储结构是密不可分的,一个算法的设计取决于选定的逻辑结构,而一个算法的实现则依赖于采用的存储结构
逻辑结构
从逻辑上描述数据,分为线性和非线性。元素之间的关系也就只有“同属一个集合”、一对一、一对多、多对多这几类。
大家记住这张思维导图,脑子里有这个框架即可。
存储结构,又称物理结构
数据结构总要存储在计算机中,那么该如何存储呢?这时候就产生了存储结构,存储结构就是用计算机语言实现的 逻辑结构。
主要有顺序存储、链式存储、索引存储、散列存储。
- 顺序存储:
定义:占用一块连续的空间,把逻辑上相邻的元素存储在计算机中物理位置也相邻的单元中。
特点:任意元素均可随机存取、地址连续、依次存放。常用数组来表示顺序表
评价:(从空间、时间、适用情况下)顺序表在空间上由于数组长度不可变,会存在闲置/溢出,存储密度为1;在时间上,顺序表随机存取——时间复杂度为1,但是在插入删除中,需要移动后面元素——时间复杂度为n;顺序表适用于表长变化不大,且事先可知变化范围,少插入删除操作的情况。
- 链式存储:
定义:不要求逻辑上相邻的元素物理位置也相邻,用指针来表示逻辑关系
特点:只能顺序存取
评价:在空间上,链表不存在空间的闲置或溢出,但是指针占用额外空间,存储密度小于1;在时间上,顺序存取——在存放取出操作时按链表一个个找——复杂度为n,但在插入删除中可以直接找到该元素——复杂度为1;适用于长度变化较大,且频繁插删的情况。
- 索引存储:
这个接触不多,不太熟,容我看看书 哈哈!
定义:在存储元素信息的同时,建立附加的索引表。索引表的每项称为索引项,包括关键字和地址
评价:
- 散列存储:
定义:又称哈希存储,由结点的关键码决定结点的存储地址,而散列函数来表示元素的存储位置(下标)与关键码之间的对应关系。例如,(24,10,32,29,17),散列函数为取余,得知下标分别为{4,1,2,9,7},根据关键码把结点存放进数组中。
评价:检索、增删操作都很快,但缺点是如果散列函数不好,会出现冲突。
运算
数据结构的运算包括运算的定义和实现。
定义是针对逻辑结构,指出运算的功能;实现是针对存储结构,指出运算的具体操作步骤,进而用代码实现。
算法
好的算法要具有五个条件:正确性、可读性、健壮性、速度快、低存储。
算法首先必须要正确,其次应该有恰当的备注和变量命名使它具有良好的可读性;再通过添加一些判断循环语句,使得在输入非法数据时有合适的处理,减少出错,能够应对大部分情况;最后优秀的算法要尽可能降低它的时间和空间复杂度。
时间复杂度
是指算法基本运算的执行次数。在分析中,可以只考虑对运行时间贡献最大的语句的重复次数 来计算时间复杂度
时间复杂度还是很重要的,有时做题中一眼就能看出程序的时间复杂度,但让自己规范的表述其推导过程就不会,所以大家还是需要经常练习的 。
空间复杂度
定义:算法占用的空间大小。有些程序除了存放自身数据、指令的空间外,还需要辅助空间,空间复杂度只计算辅助空间。不需要额外空间时,复杂度为1
在递归中,每次递归都需要调用一个栈来保存调用空间,所以阶乘递归的空间复杂度为n。
递归程序一般用公式递推
非递归程序比较简单,可以直接累加。
举个例子,加深一下对时间复杂度的理解吧。
大家还记得斐波那契数列嘛?就是那个递归来做,算法很简单;然后我自己做就没做出来的那个。。。
递归算法中,时间复杂度为指数阶,属于爆炸增量,要尽量避免
递归算法:
Fib1(int n){
if(n<1) return -1;
if(n==1 || n==2) return 1;
return Fib1(n-1)+Fib2(n-2);
}
算法改进:非递归
int Fib2(int n) {
if (n < 1) return -1;
int *a = new int[n + 1];//定义长度为n+1的数组,0空间不用
a[1] = 1; a[2] = 1;
for (int i=3;i<n+1;i++)
a[i] = a[i - 1] + a[i - 2];
return a[n];
}
算法2中,时间复杂度从指数阶降到多项式阶,算法效率可提升太多了。但是他用到了一个辅助数组来记录中间结果,所以空间复杂度为n。典型的空间换时间。
但算法2中,中间结果只是为了下一次用,根本不需要记录,所以可以再次改进,用迭代法
int Fib3(int n) {
if (n < 1) return -1;
if (n == 1 || n == 2) return 1;
int s1 = 1, s2 = 1;
for (int i=3;i<=n;i++)
{
s2 = s1 + s2;//辗转相除法
s1 = s2 - s1;
}
return s2;
}
迭代法就是一种不断用变量的旧值递推出新值的解决问题的方法,也就是辗转相除法。
暂时写到这吧,后续再不断增加内容,拜拜了您嘞
“为生民请命,为天地立心,为往圣继绝学,为万世开太平”
——Galaxy.Z