关于数据结构的学习
开始重新学习数据结构,选择了《大话数据结构》这本书。好好学习,常记录。在毕业找工作之前,打好基础。
为什么会有数据结构这种东西存在,它是什么?
早期的计算机是设计来解决数值计算的问题的,计算机解决问题时,是需要先从具体的问题中抽象出数据模型,再配以解决问题的算法来使用这种数据模型,最终达到解决问题的目的。
后来,人们开始利用计算机来解决非数值的现实问题,而这些非数值问题之间的关系可谓错综复杂,前人开始对这些数据之间的关系进行整理,最后形成了数据结构这样一门学科。专门用来研究数据对象之间的关系以及他们的操作等等问题。
数据结构和算法可以说谁也离不开谁,数据结构本身的实现就要依赖于算法,而算法的魅力也得益于数据结构作为基础,才能够解决那复杂的问题。
说得更简单点,就是人们在用计算机解决现实问题的时候,发现要把这些现实问题抽象出数据模型,再用计算机去解决它是一个很重要的问题。然后就有人专门开设了数据结构这样一门学科来研究它。而我们今天后来人学习数据结构也就是学习前人总结出来的一些典型的数据对象之间的关系。
如何衡量一个算法的优劣?
算法,其实就是解决问题的思路,然后用代码去实现它。那根据什么来评判一个算法的优劣呢?计算机中是根据一个程序的时间复杂度,空间复杂度来判断的,好的算法自然就是运行时间短、占用内存小啦。不过主要研究的还是时间复杂度。
通常设计算法时,会通过程序执行次数来预先判断一个程序的时间复杂度,而忽略其他影响程序运行时间的非确定性因素,比如,CPU 的运算速度,编译产生的代码质量等。
下面研究时间复杂度如何表示,这种体现时间复杂度的记法称作大 O 计法。典型的有以下几个例子。算法的优劣是针 n 足够大时才有意义的,一般考虑的也是最坏的情况的时间复杂度。
推导时间的复杂度的规则:
- (1) 用常数 1 代表所有运行次数的加法常数
- (2) 只保留最高阶项,且最高阶项系数置为 1
常数阶
//这是计算 1 ... n 的和的程序,时间复杂度为 O(1),不应该是 O(3)吗?别忘了规则(1)
int sum = 0,n = 100; //执行一次
sum = ( 1 + n ) * n/2; //执行一次
printf( "%d",sum ); //执行一次
线性阶
//时间复杂度为 O(n),不应该是 O(n + 1)?别忘了规则(2)
int n = 100;//执行一次
for(int i = 0; i < n;i++){
//时间复杂度为 O(1)
}
对数阶
//时间复杂度为 O( log(n) )
int count = 1;
while(count < n){
count = count * 2;
}
平方阶
//时间复杂度 O(n * n )
for(//执行 n 次){
for(// 执行 n 次){
}
}
常见的时间复杂度从小到大是:
O(1) < O(logn) < O(n) < O(n2) < O(n3) < O(2n) < O(n!) < O(nn)
至于算法的空间复杂度,其实就是程序运行过程中,需要的内存空间,有时候牺牲一点内存,换更少的时间是非常划算的。毕竟时间是更宝贵的嘛。
只有学会怎么判断一个算法的优劣,才能让自己写的代码效率更高,如何优化代码去让计算机运行的更加快速和高效。这就需要以估算时间复杂度为标准,在此基础上去编程。
什么是抽象数据类型?
抽象数据类型就是指一个数学模型和定义在该模型上的一组操作。概念是不是很难理解啊?举个不够严谨的例子吧,有时候这样对于理解概念,非常有帮助。
比如,对于线性表来说,食堂排队打饭的队列就是线性表的数学模型。排头的人打完饭就可以来开,末尾和中间的人可以放弃打饭,这种行为就是该模型上的操作。
学习数据结构,学的正是各种各样的抽象数据类型。更准确的说就是学习如何用代码去实现这种数学模型以及它的操作,从而能够有效的利用它来完成更高一级别的需求。