静态查找和动态查找
静态查找:数据集合稳定,不需要添加,删除元素的查找操作。
动态查找:数据集合在查找的过程中需要同时添加或删除元素的查找操作。
对于静态查找来说,我们不妨可以用线性表结构组织数据,这样可以使用顺序查找算法,如果我们再对关键字进行排序,则可以使用折半查找算法或裴波那契查找算法来提高查找的效率。
对于动态查找来说,我们则可以考虑使用二叉排序树的查找技术,另外我们还可以使用散列表结构来解决一些查找问题。
顺序查找:又叫做线性查找,是最基本的查找技术,它的查找过程是:从第一个(或者最后一个)记录开始,逐个进行记录的关键字和给定值进行比较,若某个记录的关键字和给定值相等,则查找成功,否则不成功。
插值查找(可以理解为按比例查找):
(插值查找和裴波那查找都是折半查找的优化)
插值查找是按比例查找,类似于折半查找,但是不一定是从中间开始,可以按照一定的比例开始,就像查字典一样,查Y开头的,就肯定会在后半部分查找了。
类似下图所示:
裴波那契查找算法:
裴波那契数列(F[K]):1 1 2 3 5 8 13 21 34 55 89。。。
随着数字的增加,前一个除以后一个数字会越来越接近0.618
所以比如有13个数据(13=5+8)这样前面8个数据,后面5个数据,这样mid就是黄金分割点了。所以也称为黄金比例查找法。
顺序查找、插值查找、裴波那契查找都是有序的,但是对于一些快速增长和数据量庞大的数据,不可能都使用有序查找,这时候就需要线性索引查找了。
线性索引查找:(索引就是为了加快数据处理速度的一种数据结构)
稠密索引:
右边是无序的,只能去顺序遍历查找,而左边的索引表是根据右边的查找表关键码排序整理而成的。通过对左边两次折半查找就可以找到55这个关键码,然后根据指针就可以找到相应的记录。
稠密索引适用于数据规模不大的,否则会产生数据规模庞大的索引表。
分块索引:
我们可以对数据表进行分块,让它分块有序,然后对每一块建立索引项。从而可以很好地减少索引项的个数。从列表中我们可以发现,列表的各个数据之间的顺序并没有整理,但是各个块之间有排序,才有索引表中的最大关键字,还有索引表也是有序的,这是因为各个块相对数据量较小。
倒排索引:
二叉排序树(二叉查找树):
所以对于无序排列来说,添加数据可以在最后直接添加,删除时可以将要删除的元素和最后一个元素对换,然后删除最后一个元素,这样就不用像平时删除元素那样,然后一个一个向前移动了。
所以对于无序的排列数来说,要找出一种查找,添加和删除都比较相对便捷的方法,所以引出了二叉排序树。
整体来说就是小的放在左子树,大的放在右子树。
70先作为根结点,105比70大放在右边,115比105大放在右子树,104比70大但比105小放在左边,67吧70小放在左边,46比70,67都小放在左边,其他的同理。
二叉排序树又称为二叉查找树,它或者是一课空树,或者是具有下列性质的二叉树:
a.若它的左子树不为空,则左子树上所有结点的值均小于它的跟结构的值;
b.若它的右子树不为空,则右子树上所有的结点的值均大于它的跟结构的值;
c.它的左、右子树也分别为二叉排序树(递归)。
二叉排序树的查找和插入:
中序遍历结果是: 46 67 70 99 104 105 109 111 115 完全是按照从小到大的顺序排列。所以说即使数据是无序的,但是只要按照二叉排序树的理念排列后,得到的数据是有序的。 但是二叉排序树不仅是为了排列顺序,还为了提高查找、插入和删除的速度。
平衡二叉树:
5 9 3 7 1 4 6 8 2
转换为二叉排序树为:
查找9,需要2次查询。但下图查询9需要9次查询。
虽然上面第二个图也是(1-9)的二叉排序树,但是相对第一个图来说,出现了排序的极端情况,所以我们就考虑如何合成查询效率比较高的二叉排序树。
平衡二叉树:要么Ta是一颗空树,要么Ta的左子树和右子树都是平衡二叉树,且左子树和右子树的深度之差的绝对值不超过1。(平衡二叉树是二叉排序树的一种)
平衡二叉树的实现原理:
把二叉树生成的时候构造成平衡二叉树主要就是为了防止极端情况的出现,提高数据的操作效率。
我们将二叉树的结点上的左子树的深度的值减去右子树的深度的值称为平衡因子BF(Balance Factor),平衡二叉树就是一棵二叉树上所有结点的平衡因子的绝对值小于等于1的树。
上图的查找效率是很低的,所以要转换为平衡二叉树。
转换顺序为:
1.
当插入到1的时候,我们就发现左右深度的之差大于1,这就需要我们进行整理(旋转)了。【旋转有左旋转/右旋转】
2.如果平衡因子大于1且为正数。(左子树减右子树)则右旋转。这时候2就是跟结点,3成为右子树。
3.平衡因子大于1且为负数,则左转。
旋转后:
4.继续添加6后,发现了对于2来说,平衡因子大于了1.
转换后为:
对于结点4来说,肯定是不对的。因此要对3进行处理。
一个结点的右子树的最左边的那个孩子事实上可以放在这个结点的左子树最右边的孩子位置上。(同时3比4小,肯定在4的左子树)
所以转换后为:
5.插入7的调整,原理如上述。
调整后:
6.结点10,9的插入。
**当10、9插入时,导致4,6,7的平衡因子均大于1了。
我们要搞定其中关键的7结点。**
变换后:
但是发现10的右子树9小于10,不合理。
我们返回第一个图,会发现4 6 7的平衡因子都是负数,10的平衡因子为正数,所以要先对10结点进行旋转。
然后再对7进行旋转:
7.结点8的插入。
此时4平衡因子是-2,6的平衡因子是-2,9的平衡因子是1。所以先对结点9进行旋转。
接着对结点6进行旋转。(对于8的处理,因为8比7大所以在7的右边,又比9小所以在9的左边)。
转换后:
这就是最终结果了。
多路查找树:
对于上面的二叉树来说,如果树的结构过于庞大就会导致效率的降低,所以出现了多路查找树。
多路查找树的特点是:其每一个结点的孩子树可以多于两个,且每一个结点处可以存储多个元素。
多路查找树中的每一个结点都具有两个或者三个孩子我们称之为2-3树。同时2-3树所有的叶子都在同一层次。
一个结点拥有两个孩子和一个元素我们称之为2结点,Ta根二叉排序树类似,左子树包含的元素小于结点的元素,右子树包含的元素大于结点的元素。不过与二叉排序树不同的是,这个2结点要么没有孩子,要有就应该有两个孩子,不能只有一个孩子。
这样当一个结点拥有两个元素,三个结点时候就是3结点。要么没有孩子,要么有三个孩子。同时关于结点元素大小和子树大小关系如上面所述。
2-3树:
散列表(哈希表)查找:
顺序表查找和有序表查找都在比较的过程中花费了大量时间,因此散列表有没有可能对此进行改进。
记录的存储位置=f(关键字) 散列技术是在记录的存储位置和它的关键字之间建立一个确定的对应关系f,使得每个关键字key对应一个存储位置f(key)。