• 数据结构 练习 20-查找 算法


    前言

    查找分为:静态查找和动态查找。静态查找利用算法查找序列或是集合里是否存在某个元素,而不对序列或是集合做出任何改变;动态查找指查找后往序列或是集合里增加或删除元素。
    参考文献:《算法导论》,维基百科, JULY的博客

    分类

    静态查找包括:二分查找,顺序索引表的查找,斐破那楔查找(略),插值(略);

    动态查找包括:二叉查找树(二叉排序树),平衡树(AVL),B树。

    再接下来的部分,我们将依次分析二分查找,索引查找,二叉查找树和平衡树,B树。并给出相关代码验证。

    二分查找

    原理就不多讲了 ,直接上代码吧!

    void BinarySearch(int* Data,int n,int m,int key,int* loc)
    {
    	if(n>=m) throw "invalid argument";
    	if(m-n==1) 
    	{
    	 if(Data[n]==key)
    	 {
    		 *loc=n;
    	 }
    	 if(Data[m]==key)
    	 { 
    		 *loc=m;
    	 }
    		
    	 return ;
    	
    	}
      int i=(m-n+1)/2;
      
      if(key>Data[i])
      {
        BinarySearch( Data, i+1,m,key,loc);
      
      }
      if(key<Data[i])
      {
      BinarySearch(Data,n,i-1,key,loc);
      }
      if(key==Data[i])
        *loc= i;
    
    
    }
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	int a[5]={1,3,6,8,9};
        int key=8;
    	int i=-1;
    	int *loc=&i;
     BinarySearch(a,0,4, key, loc);
    	
    	std::cout<<*loc;
    
    	return 0;
    }
    
    

    复杂度lg(n)。

    推荐一个JULY大牛写的:http://blog.csdn.net/v_july_v/article/details/7093204
    Binary search的前提是 数组已经排好序。百度曾经有道面试题:在一个数组里查找绝对值最小的数,就是用这个思想。

    索引顺序表的查找

    大体意思如下图,先对数组分块,然后抽取最大值。有点类似数据先清洗分解数据,按策略分开。复杂度看树高了。


    二叉查找树

    这是动态查找树的一种,操作包括:查找,删除,前驱,后继。与二分查找很相似,但是其插入,删除几乎不影响树的总体结构,即维护代价很小,因此常用作数据的查找。

    查找,删除的平均复杂度跟lg(n)一个数量级。但是BST(binary search tree) 的形状不唯一,导致复杂度可能为O(n)(最坏)。为了防止这种情况,我们引入两种变型的二叉树。AVL(平衡二叉树),和RBT(红黑树)。

    AVL

    这种树的定义:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树(http://baike.baidu.com/view/593144.htm)。

    AVL主要在二叉树的基础上维护BF(balance factor)<=1。如此一来,查找,删除的效率就不会出现不稳定,能维持在lg(n)。

    为了在维护成本和查找,删除效率之间做个平衡,平衡二叉树出现了。它多了一个color,但是总体上树的层数不如AVL分布均匀,c++里的很多容器就是RBT。

    RBT

    红黑树的查找,删除的维护成本没有AVL高。这也是导致RBT查找效率不稳定的原因,凡是都是两面的。红黑树还引入了一个color,但是其维护成本也只有lg(n),不是很大。

    因而,RBT在保持查找效率稳定的前提下,又没有增加太多的维护成本,不失为一种好的算法。其查找,删除复杂度能维持在lg(n)数量级。

    B树,B+树

    我们知道,红黑树在数据量小时,效率还是可以的。但是当数据量很大,数据没法装入内存时,问题就来了,如果我们把数据放到硬盘上,引入所谓的二次索引,那么对硬盘的I/O就很频繁了,导致速度很慢,因为硬盘的查询,等待,以及数据传输的时间跟内存的读取时间不在一个数量级上,因此对于像数据库索引,文件系统...我们要尽量提高查询,删除的速度。于是乎,B树应运而生,且不管哪个大牛发现的。B树试图只把根保留在内存,其余节点放在硬盘。那么为什么就减少了I/O呢?我们先来看看B树的定义吧:引用《算法导论》。

    可见,B树的阶数不只是2时,这样可以大大降低高度,也就降低了访问磁盘的次数,而且B树的高度固定,为:log(ceil(m/2))((n+1)/2)。(记住)。

    还有一种树B+,这种树的引入,进一步降低对I/O的访问。B+是在B的基础上改进,内部节点不存放关键字信息,全部关键字的信息放在叶子节点中。非终端节点存储关键字的索引信息。这样有俩个好处:

    1  一个盘块能容纳的关键字数更多,减少了对I/O的访问;

    2 每个节点的查找或是删除都是从根节点到叶子节点的查找,这样访问的效率很稳定。

  • 相关阅读:
    lnmp mysql高负载优化
    vi查找替换命令详解
    学习资料汇总
    App应用推广
    sed 命令详解
    10个经典的Android开源应用项目
    Java基础学习总结——Java对象的序列化和反序列化
    Java制作证书的工具keytool用法总结
    Linux下安装Tomcat服务器和部署Web应用
    谈谈对Spring IOC的理解
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3170170.html
Copyright © 2020-2023  润新知