第一章 绪论
1. 作者的话
??大家好,首先感谢大家能看我的文章!今天开始,我要学习一门新的课程 - 数据结构与算法,所以该体系的文章是我在学习这门课程的过程中的一些总结,也就是我的笔记。如果有写的不合适或者有错误的地方,欢迎大家在评论区进行指正。最后,还是希望看到我文章的朋友们能有所收获,再次感谢。
2. 为什么要学习数据结构与算法
??可能有些人认为,学习数据结构与算法的用途并不大,好像在开发中很少会用到那些二叉树、队列、堆栈、图等等知识。但这是一种错误的想法,因为学习数据结构与算法对我们自身带来的价值并不局限于这些硬生生的数据结构模型,而更有价值的是我们学会了一种思想,这种思想可以让我们轻而易举的将生活中的实际问题转化为计算机语言进行表示。因此,如果你想在开发过程中能够更好的去解决实际问题、更能充分的去利用计算机工作,我们就应该学好数据结构与算法这门课程。
3. 数据结构与算法的作用
??其实在我们的生活中,有很多场景就类似于数据结构中的某一种。我们来举几个简单的例子,大家都知道栈最大的特点就是后进先出,弹匣大家都见过吧,就算没见过真的,玩具总该玩过吧!想象一下,最先压进弹匣的子弹是不是最后才被打出来的,而最后压进弹匣的子弹反而是第一发打出来的。这其实就是一个典型的栈的实例。 ??还有我们手机里的通讯录、医院里的叫号系统、吃鸡游戏里面的背包、导航软件里的选择路线规则等等等等… 都离不开数据结构的存在。最后借用恒哥的话:但凡有数据“扎堆”的地方,都有数据结构的影子;但凡有数据结构的地方,都脱离不了算法的“折磨”。
4. 数据结构的概念
4.1 名词解读
??在数据结构中,我们会涉及到许多专业术语,我们有必要来了解一下。 ??数据元素: 它是数据的基本单位,也叫做节点或记录,在计算机中通常最为整体处理。 ??数据项: 数据元素可有若干个数据项组成,它是数据不可分割的最小单位。 ??数据对象: 是性质相同的数据元素的集合,是数据的子集。
4.2 什么是数据
??既然我们要研究数据结构,那我们首先得知道数据是什么东西?平时我们在网上看电影、下载音乐、查看文档、图片等,我们获取的东西,其实就是数据。再高级一点,我们把想要计算的信息传入计算机中,计算机经过运算后返回给我们结果,这其实就是人和计算机形成数据交互的过程。 数据:是描述客观事物的符号,是计算机中可操作的对象,是能被计算机所识别,并输入给计算机处理的符号集合。 由此可见,数据就是能输入到计算机中的符号,并且这些符号要能被计算机所识别和处理。在这里有些人可能会问,音乐、图片、视频并不是符号,那为什么也能被成为数据呢?那是因为它们也可以通过编码的手段,被转换为字符数据来处理。
4.3 数据结构
??数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。在计算机中,数据之间并不是互相独立的,而是在不同场景下存在着特定的关系,这些关系其实也就是数据结构的“结构”二字的体现。按照视点的不同,数据结构可以分为逻辑结构和物理结构,我们继续往下看。
4.4 逻辑结构
??逻辑结构其实就是,数据对象中数据元素之间的相互关系。逻辑结构可以分为:集合结构、线性结构、树形结构、图形结构。 ??集合结构: 多个数据元素同属于一个集合内,它们之间并没有其他关系,仅仅在同一集合内而已。如下,大圆就是集合,里面的就是数据元素,它们就只是在同一个大圆内,无其他关系。 ??线性结构: 该结构中的元素之间是一对一的关系。 ??树形结构: 数据元素之间存在一种一对多的层次关系。 ??图形结构: 数据元素之间存在多对多的关系。我们要注意,每个数据元素可以看作一个节点,如图中圆圈;元素之间的关系用连线表示,并且可以是有向的,有向的用箭头来连线。
4.5 物理结构
??物理结构也可以成为存储结构,它是指数据的逻辑结构在计算机中的存储形式。存储结构必须能够正确反映数据元素之间的逻辑关系。数据元素的存储结构分为两种:顺序存储和链式存储。 ??顺序存储结构: 就是把数据元素存放在地址连续的存储单元中,其数据的逻辑关系和物理关系是一致的。举一个典型的例子:数组。 ??由于真正用于某些场景的结构往往是复杂的,不可能都按照顺序结构,因此引出链式存储结构。 ??链式存储结构: 它是把数据元素存放在任意的存储单元里,这组存储单元可以是连续的,也可以是不连续的。但这样的存储关系并不能直接反应其逻辑关系,因此需要有一个东西来存储数据元素的地址,这样就可以通过地址来找到该数据元素。显然,链式存储结构更加灵活。
5. 算法
5.1 数据结构和算法的关系
??很多人都在讨论这二者到底有没有关系,在我看来,二者相辅相成,数据结构是将一些有着逻辑结构的数据元素以某种物理存储方式进行存储;而算法必定是有自己的规律的,这种规律往往有和数据的存储方式相关。所以只有算法自己,它可能只能实现一些简单的有规律的逻辑;但如果没有了算法,数据结构的用武之地也就大大减少了。只有二者结合,我们才能够更好的将生活中遇见的复杂问题,巧妙化解。
5.2 算法的定义
??算法,算法,通俗的讲就是问题的解决方法与步骤。 ??算法: 是解决特定问题求解步骤的描述,实在计算机中表现为指令的有限序列,并且每条指令表示一个或多个操作。 ??算法的特性: 输入、输出、有穷性、确定性、可行性。 ??输入、输出,都比较简单。一个算法可以有零个或多个输入,个别情况下算法可以没有输入,比如打印一句”你好!“ 并不需要输入。但是算法必须有一个或多个输出,如果没有输出,那么这个算法本身也就没有意义。 ??有穷性,它是指算法在执行有限的步骤后,会自动结束算法,而不会陷入死循环,并且每个步骤都可以在可接受的时间内完成。 ??确定性,算法的每一步骤都具有确定的含义,不会出现二义性。 ??可行性,算法的每一步都必须是可行的,也就是说,每一步都能够通过执行有限次数完成。
5.3 算法设计的要求
??正确性: 算法至少应该具有输入、输出和加工处理无歧义性、能正确反映问题的需求、能够得到问题的正确答案。 ??可读性: 算法设计的另一目的是为了便于阅读、理解和交流。 ??健壮性: 当输入数据不合法时,算法也能做出相关处理,而不是产生异常或莫名其妙的结果。 ??时间效率高和存储量低: 好的算法应该满足这个条件。
5.4 如何判断算法的效率
??事后统计法: 从名字都可以看出来,这种方法主要是通过设计好的测试程序和数据,利用计算机计时器对不同算法编制的程序的运行时间进行比较,从而确定算法效率的高低。但它不好的地方在于,必须实现编写好程序、算法比较依赖计算机硬件和软件等环境因素、算法的测试数据设计困难。因为缺陷较多,并不常用。 ??事前分析估算法: 在计算机程序编制前,依据统计方法对算法进行估算。
5.5 算法的时间复杂度
??概念太抽象,大家可以直接百度,在这里我只说我自己的理解。算法的时间复杂度主要探究的是问题输入规模 N 的数量级,不是算法的具体执行次数。说白了就是按级别划分,举个简单的例子,你有100万元,他有900万元,虽然他确实比你多很多,但是你俩都是百万富翁。常见的时间复杂度级别如下: ??常数阶: 就是无循环、无递归、与问题输入规模 N 无关的、逐行执行的代码。
int a = 1;
int b = 2;
int c = a + b;
如图: ??线性阶: 与问题输入规模有关,主要是一层循环的代码,多个一层循环可以并列但不能包含。
int n = 10;
for (int i = 0; i < n; i++) {
System.out.println(i);
}
for (int i = 0; i < n; i++) {
System.out.println(i);
}
如图: ??平方阶: 与问题的输入规模有关,一般是双层循环嵌套,双层云环次数不同也是平方阶。O(nm)
int n = 10;
for (int i = 1; i < n; i++) {
for (int j = 1; j < n; j++) {
System.out.println(i + j);
}
}
如图: ??对数阶: 与问题的输入规模有关,主要是一层循环迭代或递归代码。
int count = 1;
int N = 100000;
while (count < N)
count = count * 2;
如图: ??常见阶比较: 时间复杂度简单计算,忽略常数,保留幂高项、且忽略幂高项的系数。
5.6 算法的空间复杂度
??算法的空间复杂度通过计算算法所需的存储空间实现,算法空间复杂度的计算公式记作:S(n) = O(f(n)),其中 n 为问题的规模,f(n) 为语句关于 n 所占存储空间的函数。
总结
??本章,主要学习了数据结构和算法的一些基本理论性知识,从下一章开始,我们正式进入代码实现环节,继续加油努力。
|