我们学习数据结构之前的那些查找,比如说查找数据库,仅仅是查找,这种自作查找操作的查找表称为静态查找表
而在查找过程中,同时插入查找表最后中不存在的数据元素,还可以删除某些不要的项的情况,叫做动态查找表 :查找时插入数据元素,查找时候删除动态元素
静态查找表:
1:顺序查找表
一般在普通的数据集中,比如说数组,要找到我们要的那个记录就是判断关键字和我们的关键字是否一致,一般是判断两次,关键字是否相同,是否越界
这并不是完美的,可以增加一个哨兵,我们把要搜索的数据从1开始存放,到n,a[0]放哨兵(也可以是最后一个),然后在一个循环里面判断关键字,返回后判断一次,如果返回的值的下标如果是0(其他写法的话,也有可能是最后一个),证明是没找到结果,这样处理就少了半数的判断,效率提高不知一点点啊
顺序表对于表里面的数据是否有序不作要求,因此这个查找通用,但是效率不是很高,特别是数据量比较大的时候
鉴于这个原因有序表的查找就显得高效多了
2:有序表查找
折半查找
有序表查找中,最有代表性的查找方法是折半查找
折半查找的思路简单就是,和那个非常6+1差不多,给一个区间,比如说猜一个数,范围1-100,先说50,李咏会说大了或者小了,如果小了,就猜51和100间的中值75,这样下去很快就出答案了,这就是典型的折半查找的例子
实际代码的处理是
int low =0,high = n,mid;
while(low<high)
{
mid = (low +high)/2;
if(key<a[mid])
{
high = mid-1;
}else if(key>a[mid])
{
low = mid+1;
}
else
return mid;
}
循环的条件是low <high 这样就消除了边界问题
折半查找的效率已经是很牛逼了,但是这还没到最完美,假说,查字典,一般记录值是a~z按序列的,如果我们要查找apple显然不是从a-z的中间开始,因为明显可可知道在记录的前面,这时候折半还没有达到最优,这时候要说另外一个算法,插值查找
插值查找
对于上面说折半查找的这种情况效率不高,那么插值查找就要在mid这个地方下功夫,到这多少,折一半,还是1/4,还是1/8
由于折半查找是不管key是多少,都是一次折一半,插值查找会根据这个key的值来确定mid的值,个人觉得这也算是一种权重把,不像折半那样管你是谁,老子就折一半,插值根据这个key的值来做一些影响,具体的赋值是
本来 :mid = (low + high)/2 = low/2 + high/2 = low + high/2- low/2 = low + 1/2(high - low)
插值查找就把这个1/2给做了改动 改为(key -a[low])/ (a[high] - a[low] ) ,这样可看出,key越小,插得值越小,key越大 插的值越大,这样字普遍来说更加高效
还有另外一种有序表的查找方法,叫费波那契查找 利用了黄金分割原理来实现的
事实上,虽然折半,插值,费波那契 ,这些查找虽然十分高效,但他们的要求是记录有序,但是在很多情况下,要查找的记录有序的话,代价太高,因此还要考虑到普通的并非有序的记录,有对于无序的数据又要很快的查找到记录怎么办呢,这里有一种方法,叫建立索引,把数据的位置拿出来放到一张表中,这样查表就可以查的记录了(快吧 -!!) 索引有多种,我们就学重点看三种,稠密索引 ,分块索引,倒排索引
动态查找表
对于有序的数据 :如果是使用存储,我们在查找的时候可以用非常高效的算法,如折半查找,插值查找,费波那契查找,但是,我的数据是会增加的,如果有一个新的记录进来的新的记录的大小处于原来的数据集合的中间位置你那么如果要插入的话,那就要移动半数的数据,有或者要删除顺序存储中的中间的一个数据,那么后半部的数据就都要往前移动一步,太麻烦了,效率太低,如果又要有序,又要插入高效,怎么办呢,这就要用到二叉排序树
二叉排序树
二叉排序树,他是排过序的二叉树,也就是双亲节点的数据大小比左孩子大,比右孩子小,这种树查找的时候先从根结点开始比较,等则返回,比根结点大就去到右孩子,比跟节点小则去左孩子,这样的话最多查找到叶子就出结果,次数最多为层数插入新节点的时候也是这样,比较,找到合适位置就插入,新节点插入都是叶子,这样字貌似解决了有序且插入高效的难题,但顺序是还不是最好的解决方案,我们知道,查找的最差情况是数的层数,如果这颗二叉树每层都只有一个孩子那么处于叶子位置的节点就会好倒霉,查找他太慢,这个时候,会想到,完全二叉树是最理想的情况,但是往往给出的数据没有那么巧,我们可以尽量使得二叉树的左右子树一样高,这样的话,节点分布比较均匀,查找更高效,因此提出了平衡二叉树
平衡二叉树
平衡二叉树的要求是每个节点的左右子树的高度之差不能超过1,这就有3种可能,左子树比右子树 的高度 大1 小1,相等,但是新插入的点是未知的,所以很有可能会打乱平衡,因此,要对不平衡的子树进行调整
经过调整后的二叉树变平衡了,这样的话查找效率就高了,虽然avl二叉树比二叉排序树的效率要高的多,但是我门也看到插入或者删除一个节点的时候,经常要进行调整旋转操作,这样又付出了一些时间,能不能做一个折中处理呢,查找效率又高,调整有没那么频繁呢,答案是有,叫红黑树(red black tree)RB树,(普遍的实际应用中验证,红黑树的效率要比avl树高一些)
在海量数据处理中,二叉树的规模会非常大,为了缓解这个为问题,提出了B树,也就是不止二叉,多一些节点那么树的高度就会小,查询的效率也会高,B树也被国内称为B-树,B+树是B树的拓展,B*树是B+树的拓展,这个还不熟悉,以后再写心得