闲来无事,正好看见考研时复习数据结构的王道书,说实话当时学的时候追求了速率,有些地方还是不求甚解,现在回想一下已经忘得七七八八了,只记得许多课后习题看完答案之后有种“卧槽,还能这么写?”这样的感叹,所以打算认真的更一下数据结构。
绪论
(一)数据结构三元素
一般来讲呢,数据结构就三个要素,逻辑结构,存储结构,以及数据运算。也就是说一个算法,你设计的时候呢,是基于逻辑结构的,比如说树啊,图啊,线性表啊这些,在我们脑子里是这么个结构,但是真正实现出来,是靠他的存储结构的。也就是说你这个数据,你到底给他存在哪个存储单元以及这些存储单元之间的联系。
- 逻辑结构
这张图是百度来的,差不多逻辑结构节这么些了 - 存储结构
- 顺序存储:顾名思义嘛,就是逻辑结构上相邻的元素,在物理位置上也分配相邻的存储单元。优点是能随机存取,而且每个存储单元除了数据之外什么都不存,从这个方面来讲的话占用空间最少;缺点是只能占用一整块的存储空间,可能会产生较多碎片,而且也不能利用碎片空间
- 链式存储:链表都知道吧,就是通过指针来实现逻辑上的相邻,但是实际物理存储可以随便存,只要当前元素的尾指针指向下一个元素,逻辑上还是相邻的。优点是可以充分利用每一块空间,缺点也很明显,要存指针的头和尾额外占用空间,而且只能实现顺序存取。
- 索引存储:存储信息的时候加一个简历一个索引表,通过这个可以找到那个关键字存在了哪块地址。优点很明显,检索速度快,看一眼表就知道,缺点也是,你存数据的时候要额外开辟大量空间存你这个索引表,而且你改数据的时候肯定也要把这个表也给改了
- 散列存储:根据元素的关键字直接计算出这个元素的地址,这么说可能还比较陌生,但是提一下他的另一个名字Hash(哈希)存储,是不是就熟悉了许多,优点是增删改查操作都很快,缺点就是他需要构建一个散列函数,要是这个函数构建的不好,会有很多冲突,而解决冲突肯定要花费时间空间【具体有关怎么构建函数,怎么解决冲突,以后会讲的】
【注】 顺序存取和随机存取,只看字面意思可能理解不了,所以我就稍微解释一下
随机存取:也就是比如你知道他在第逻辑结构上排在第八,由于存储地址都是连续的嘛,你能很容易的找到他的实际存储地址,不用浪费额外的时间去找,所以很快
顺序存取:想一想咱们的链表,你即使知道他在第八个,你想找到他的位置的话,你还得看表头在哪里,然后表头指向第一个,在看第一个指向的第二个在哪里,然后看第三个,,,,直到找到第八个,因为他是存的没有规律,只能通过指针一个一个的找,就比较慢
散列存储和索引存储,都是一个表,那么最主要的区别是什么呢,主要的区别就在于查找上,想一想咱们的一系列查找算法,折半查找啊 顺序查找啊等等,都是要一个一个比对,什么意思呢,就是你即使知道了咱们要找的数字是86,但是你得通过各种算法去比对,看咱们要的这个数字,也就是关键字存在表上的哪个地方,然后再根据表找到这个关键字对应的地址并进行操作。而哈希表就不一样了,他有一个关键字和地址的直接映射,就是通过上文提到的散列函数,有了这个函数之后,你在想找一个关键字,直接通过这个函数计算一下,就知道他具体存在哪里,一步到位。当然,用这个方法首先要有一个合适的散列函数,而且冲突是无法避免的,,具体到时候再讲吧
- 数据运算
(二)算法
经常说算法算法的,其实大家也都知道这是个什么东西,通俗点说就是解决问题的方法步骤嘛,这里就写一些规范化的语言吧,用规范的语言描述一下这个东西
算法的五个特性,有穷性,确定性,可行性,输入,输出。其中输入可以有零个但是输出至少得有一个。其他就字面意思
而一个好的算法。通常来说追求的就是一下几点
- 正确性
- 可读性
- 健壮性:即使你不按要求使用,我也不会系统崩溃,不会产生一些莫名其妙的结果
- 效率与低存储量要求
效率
怎么衡量一个算法的效率呢,也就是事件复杂度和空间复杂度,跑得快,占内存少,又能达到想要的效果,你就是一个高效的算法。
这里主要提一句,这两个复杂度一般都是按照量级表示的,就比如说你一个程序复杂度是O(n),另一个是O(n^2),他俩加起来还是后者,主要就表示是这个数量级的就行不用那么精确。
…序章就这样吧,下节更线性表里的顺序存储–顺序表以及一些相关的算法题