大家好,今天开始,我们将一起来学习数据结构这门课。亲爱的读者们,你们可能学过C、C++、Java、python、Golang、C#等编程语言,但是不知道能干啥?写个"Hello,world",还是判断平年闰年?嗷,还会冒泡排序呢!但是这些用法都很基础啦!想更上一层楼吗?来学数据结构就对啦!掌握编程语言相当于会砌猪圈的泥瓦匠,学完数据结构就会盖个小平房啦!同时还可以一窥构筑摩天大厦的奇门武功! 通往大佬的修行之路,将从这里起步。
“数据结构”是计算机以及相关专业课程的基础专业课之一,同时也是最重要的一门课,主要学习用计算机实现数据组织和数据处理的方法。它也为计算机专业的后续课程,如操作系统,编译原理,软件工程等的学习打下了坚实的基础。现如今,随着计算机应用领域的不断扩大,非数值计算问题占据了当今计算机的绝大多数。简单的数据类型已经远远不能满足需要,各数据元素之间的复杂联系已经不是普通的数学方程式所能表达的了,因此不论设计系统软件还是应用软件都会用到各种复杂的数据结构,因此掌握好数据结构课程的知识对于提升解决实际问题的能力会有很大的帮助。实际上,一个好的程序无非是选择一个合理的数据结构和好的算法,而好的算法的选择在很大程度上取决于描述实际问题所采用的数据结构,所以想写出好的程序,大家仅仅学习计算机编程语言是不够的,必须扎实地掌握数据结构的基本知识和基本技能。
笔者博客中的数据结构有关的内容将全部用C语言实现。
关于数据结构的相关定义、逻辑结构与存储结构、数据运算等一些简单明了的概念我就不一一介绍了,大家好好熟悉课本即可。我就在这里简单说一下我对抽象数据类型的理解,这个地方在刚开始学的时候理解起来确实会有一些难度。我认为抽象数据类型和数据类型是类似的。数据类型是一组性质相同的值的集合和定义在此集合上的一组操作的总称,是某种程序设计语言中已经实现的数据结构。以C语言中的基本数据类型为例,int类型的含义就有两种:
- 它是一组性质相同的值的集合:一个由 -2147483648~2147483647 的所有整数所组成的集合。
- 在此集合上的一组操作:例如+,-,*,/,取余等等。
而抽象数据类型(Abstract Data Type,ADT)指的是用户进行软件系统设计时从问题的数学模型中抽象出来的逻辑数据结构和逻辑数据结构上的运算,而不考虑计算机的具体存储结构和运算的具体实现算法。它的基本格式如下:
ADT 抽象数据类型名
{
数据对象:数据对象的声明
数据关系:数据关系的声明
基本运算:基本运算的声明
}
举个栗子吧,我们马上就要学到一种抽象的数据类型,叫做线性表,它的数据对象就是一个连续的一维数组。数据关系就是表中的元素呈线性关系。基本运算有线性表初始化,线性表删除,插入删除元素等等。等到后来学习的时候,大家会理解得更为透彻。
下面是算法。同样,最基本的概念不再讲解。时间复杂度和空间复杂度是衡量算法性能优劣的两杆十分重要的秤,这里的重点是大家要会算时间复杂度。话不多说,我们直接上题。
第一题:
for (i=1; i<=n; i++)
for (j=1; j<=n; j++)
x++;
这段伪代码,它的时间复杂度是多少呢?我们来做一下简单的分析,这个代码段由两重循环组成,外层执行n次,内层执行n次,乘起来就是次,所以它的时间复杂度就是O()。
第二题:
count=0;
for(k=1;k<=n;k*=2)
for(j=1;j<=n;j++)
count++;
很显然,这段伪代码也是由两重循环组成,内循环的执行次数是n,这毋庸置疑。我们主要来分析一下外循环。设外循环的执行次数是m,假如n是一个比较大的数字,1乘以若干次2方可大于n。
1 ≤ n,外循环不结束,此时m为1。
1*2=2 ≤ n,外循环不结束,此时m为2。
1*2*2=4 ≤ n,外循环不结束,此时m为3。
1*2*2*2=8 ≤ n,外循环不结束,此时m为4。
......
1* > n,外循环终于结束,此时介于n和2n之间。
由于算法的时间复杂度和语句的具体执行次数没有关系,我们要的只是它的数量级,其余的细枝末节我们均可以忽略不计,所以无论是n还是2n,甚至是100n,都是和问题规模n呈线性关系。我们干脆令=n,求出m=logn+1。再用m乘以内层循环的执行次数n,就是nlogn+n次。由于我们要的是数量级,nlogn是n的高阶无穷小,所以"n"这个尾巴可以直接甩掉,写成标准答案就是O(nlogn)。
那么,下面两段伪代码的时间复杂度又是多少呢?欢迎留言交流。
-
int count=0; for(int i=0;i<0;++i) for(int j=i;j<n;++j) count++;
-
int i=1; int n= 100; while(i<n) i = i*2;