数据结构与算法—概述

数据结构是什么?

数据结构,可以将之分为“数据”和“结构”两个方面去理解。

数据,很好理解。都说人离不开空气,感觉剥夺实验告诉我们,人也离不开信息,而信息实际上就是对数据进行加工后得到的产物。

信息的形式多样化,所以数据的形态也多种多样:文字、数字、字母、符号、图形图像、音频视频等都可以是数据。

数据结构,实际上是一门研究数据以及数据之间存在的关系的一门课程。通过理清数据及其之间存在的关系,就可以将数据有效存储到计算机中,让计算机来处理数据。

数据的逻辑结构和物理结构

数据之间的关系(即数据结构)又可细分为:逻辑关系(逻辑结构)和物理关系(物理结构)。逻辑关系就是例如张晶的父亲是张平、张群是张平的兄弟等等这样的关系,是人为赋予给数据的。

数据之间的逻辑关系分为三种:“一对一”、“一对多”、“多对多”。图 1 中,每个孩子对应着唯一的父亲,这是“一对一”的关系;拿张平来说,他有两个孩子,为“一对多”的关系;

数据结构 PK 算法

数据结构和算法两者为互利共赢的关系,两者并不冲突。使用计算机编程解决某个具体问题时,正确的做法是:

  1. 思考如何将要用到的数据存储到计算机中;
  2. 使用什么方法解决这个问题;

数据结构解决的是第一个问题,算法解决的的第二个问题。光有数据结构没有算法,相当于只把数据存储到计算机中而没有有效的方法去处理,没有任何意义;而若光有算法,没有数据结构,就相当于一个军师有锦囊妙计,但是没有士兵。

几个学习方向

  • 线性表、栈和队列:解决的是具有“一对一”关系的数据的存储问题;
  • 树:解决的是具有“一对多”(也可以包含“一对一”)关系的数据存储问题;
  • 图:解决的是具有“多对多”(也包含“一对一”和“一对多”)关系的数据存储问题;

算法

算法,即解决问题的方法。同一个问题,使用不同的算法,虽然得到的结果相同,但是耗费的时间和资源是不同的。

运行效率体现在两方面:

  • 算法的运行时间。(称为“时间复杂度”)
  • 运行算法所需的内存空间大小。(称为“空间复杂度”)

好算法的标准就是:在符合算法本身的要求的基础上,使用算法编写的程序运行的时间短,运行过程中占用的内存空间少,就可以称这个算法是“好算法”。
调查表明,人们对于软件或者 APP 的运行效率有极高的要求,例如对于网页打开的忍耐极限是 6 秒甚至
更短,如果你设计的网页打开的时间超过 6 秒,多数人会在 4 秒甚至 3 秒的时候毫不犹豫地关掉而去浏览其他网页。在这个大背景下,一个好的“算法”更注重的是时间复杂度,而空间复杂度只要在一个合理的范围内就可以。时间复杂度的计算
计算一个算法的时间复杂度,不可能把所有的算法都编写出实际的程序出来让计算机跑,这样会做很多无用功,效率太低。实际采用的方法是估算算法的时间复杂度。

C语言程序由三种结构构成:顺序结构、分支结构和循环结构。顺序结构和分支结构中的每段代码只运行一次;循环结构中的代码的运行时间要看循环的次数。

由于是估算算法的时间复杂度,相比而言,循环结构对算法的执行时间影响更大。所以,算法的时间复杂度,主要看算法中使用到的循环结构中代码循环的次数(称为“频度”)。次数越少,算法的时间复杂度越低。

例如:
a) ++x; s=0;
b) for (int i=1; i<=n; i++) { ++x; s+=x; }
c) for (int i=1; i<=n; i++) { for (int j=1; i<=n; j++) { ++x; s+=x; } }

上边这个例子中,a 代码的运行了 1 次,b 代码的运行了 n 次,c 代码运行了 n*n 次。时间复杂度的表示
算法的时间复杂度的表示方式为:
O(频度)
这种表示方式称为大“O”记法。
注意,是大写的字母O,不是数字0。
对于上边的例子而言,a 的时间复杂度为O(1),b 的时间复杂度为O(n),c 的时间复杂度为为O(n2)。

如果a、b、c组成一段程序,那么算法的时间复杂度为O(n2+n+1)。但这么表示是不对的,还需要对n2+n+1进行简化。

简化的过程总结为3步:

  • 去掉运行时间中的所有加法常数。(例如 n2+n+1,直接变为 n2+n)
  • 只保留最高项。(n2+n 变成 n2
  • 如果最高项存在但是系数不是1,去掉系数。(n2 系数为 1)

所以,最终a、b和c合并而成的代码的时间复杂度为O(n2)。常用的时间复杂度的排序
列举了几种常见的算法时间复杂度的比较(又小到大):
O(1)常数阶 < O(logn)对数阶 < O(n)线性阶 < O(n2)平方阶 < O(n3)(立方阶) < O(2n) (指数阶)

拿时间换空间,用空间换时间

算法的时间复杂度和空间复杂度是可以相互转化的。
谷歌浏览器相比于其他的浏览器,运行速度要快。是因为它占用了更多的内存空间,以空间换取了时间。
算法中,例如判断某个年份是否为闰年时,如果想以时间换取空间,算法思路就是:当给定一个年份时,判断该年份是否能被4或者400整除,如果可以,就是闰年。

如果想以空间换时间的话,判断闰年的思路就是:把所有的年份先判断出来,存储在数组中(年份和数组下标对应),如果是闰年,数组值是1,否则是0;当需要判断某年是否为闰年时,直接看对应的数组值是1还是0,不用计算就可以马上知道。

你可能感兴趣的:(数据结构与算法—概述)