zoukankan      html  css  js  c++  java
  • 查找二 树与图的搜索

    搜索对象是一个数据的集合(称为搜索表),除了执行搜索外,还可能执行其他操作,例如添加新元素,这样可能会改变搜索表的结构。因此,搜索表可以区分为静态搜索表(表的结构不发生改变)和动态搜索表两种情况。

    常见的适用于静态搜索表的搜索方法有:顺序搜索、折半搜索、Fibonacci搜索等。

    适用于动态搜索表的搜索方法有:二叉排序算法,平衡二叉搜索算法。

    二叉排序树搜索

    二叉排序树(Binary sort Tree,BST)又称为二叉查找(搜索)树(Binary Search Tree) 。其必须为二叉排序树或者为空树,或者满足如下性质的二叉树:

    (1)若它的左子树非空,则左子树所有结点的值均小于根结点的值;

    (2)若它的右子树非空,则右子树上所有结点的值均大于根结点的值;

    (3)左、右子树本身又各是一颗二叉排序树。

    由BST性质可得:

    1)二叉排序树中任一结点x,其左(右)子树中任一结点y(若存在)的关键字必小(大)于x的关键字。

    2)二叉排序树,各结点关键字是唯一的。

    实际运用中,不能保证被查找的数据集中各元素的关键字互不相同,所以可将二叉排序树定义中BST性质(1)里的“小于”改为“大于等于”,或将BST性质(2)里的“大于”改为“小于等于”,甚至可同时修改这两个性质。

    3)按中序遍历该树所得到的中序序列是一个递增有序序列。

    二叉排序树的存储结构表示如下:

    typedef int KeyType;//假定关键字类型为整数
    typedef struct node {//结点类型
        KeyType key;//关键字项
        InfoType otherinfo;//其他数据域,InfoType视应用情况而定,下面不处理它
        struct node *lchild,*rchild;//左右孩子指针
    } BSTNode;
    typedef BSTNode *BSTree;//BSTree是二叉排序树的类型
    

      

    B-树

    当查找文件较大,且存放在磁盘等直接存取设备中时,为了减少查找过程中对磁盘的读写次数,提高查找效率,基于直接存取设备的读写操作以“页”为单位的特征。1972年提出了一种称之为B-树的多路平衡查找树。它适合在磁盘等直接存取设备上组织动态的查找表。一颗m(m>=3)阶的B-树是满足如下性质的m叉树:

    (1)每个节点至少包含下列数据域:(j,P0,K1,P1,k2,……,Ki,Pi)。其中:

    j为关键字总数,

    Ki(1<=i<=j)是关键字,关键字序列递增有序:K1<K2<……<Ki。

    Pi(0<=i<=j)是孩子指针。对于叶节点,每个Pi为空指针。

    注意:

    实际运用中没结束空间,叶节点可省去指针域Pi,但必须在每个结点中增加一个标志域leaf,其值为真时表示叶节点,否则为内部结点。

    在每个内部结点中,假设用keys(Pi)来表示子树Pi中的所有关键字,则有keys(P0)<K1<keys(P1)<K2<……<Ki<keys(Pi),即关键字是分界点,任一关键字Ki左边子树中的所有关键字均小于Ki,右边子树中的所有关键字均大于Ki。

    (2)所有叶子是在同一层,叶子层数位树的高度h。

    (3)每个非根结点中所包含的关键字个数j满足:m/2-1<=j<=m-1,m为阶数。

    即每个非根结点至少应该有m/2-1个关键字,至多有m-1个关键字。因为每个内部结点的个数正好是关键字总数加1,故每个非根的内部结点至少有m/2棵子树,至多有m棵子树。

    (4)若树非空,则根至少有1个关键字,故若根不是叶子,则它至少有2棵子树。根至多有m-1个关键字,故至多有m棵子树。

    B-树的结点规模

    B-树的算法执行时间主要是由读写磁盘的次数来决定的,每次读写尽可能多的信息可提高算法的执行速度。

    B-树的结点规模一般是一个磁盘页,而结点中的所包含的关键字及其孩子的数目取决于磁盘页的大小。

    注意:

    1)对于磁盘上一颗较大B-树,通常每个结点拥有的孩子数目(即结点的度数)m为50至2000不等。

    2)一颗度为m的B-树称为m阶B-树。

    3)选取较大的结点度数可降低树的高度,以及减少查找任意关键字所需的磁盘访问次数。

    B-树的存储结构

    #define Max 1000    //结点中关键字的最大数目:Max=m-1,m是B-树的阶
    #define Min 500        // 非根结点中关键字的最小数目:Min=m/2-1   
    typedef int KeyType;//KeyType应由用户定义
    typedef struct node {//结点定义中省略了指向关键字代表的记录的指针
        int keynum;//结点中当前拥有的关键字的个数,keynum<<Max
        KeyType key[Max+1];//关键字向量为key[1……keynum],key[0]不用
        struct node *parent;    //指向双亲结点
        struct node *son[Max+1];//孩子指针向量为son[0……keynum]
     }BTreeNode;
    typedef BTreeNode *BTree;
    

      

    广度优先搜索

    搜索图常用方法有深度优先搜索和广度优先搜索两种。它们对无向图和有向图都适用。

    广度优先搜索(BFS)类似于树按层次遍历的过程。广泛应用于求解问题的最短路径、最少步骤、最优方法等方面。

    广度优先搜索遍历图的过程中以V为起始点,由近及远,依次访问和V右路径相通且路径长度为1,2……的顶点。

    BFS(图g,顶点s)
    {
        队列Q;
        for(顶点u in g.所有顶点)    u.状态=未访问;
        s.状态=准备访问;
        s.访问深度=0;
        Q.入队(s);
        while( Q.非空() )
        {
         顶点u=Q.出队();
         for(顶点v in u.所有邻接点)
         {
          if(v.状态==未访问)
          {
            v.状态=准备访问;
            v.访问深度=v.访问深度+1;
            v.前趋点=u;
            Q.入队(v);    
           }
         }
        u.状态=已访问;
       }
    }
                
        
    

      

    深度优先搜索

    DFS类似于树的先根遍历,是树的先根遍历的推广。常用于游戏软件开发中。深度优先搜索的核心思想是在搜索到尽头时,用栈记住下一步的走向。

    DFS(图g,顶点s)
    {
      s.状态=正在访问;
      
      for(顶点v in s.所有邻接点)
      {
       if(s.状态 == 未访问)
           DFS(g,v);
       }
    
      s.状态=已访问;  
    }
    

      在遍历图的时候,对图中每个顶点至多调用一次深度优先搜索,遍历图的过程实质上是对每个顶点查找其邻接点的过程,其耗费的时间取决于所采用的数据结构。当用邻接矩阵存储图时,查找一个顶点的邻接点所需时间为O(n)(n表示图中顶点数目),则总的时间复杂度为T(n)=O(n^2).

    ---------------------------------------------------------------------------------

    参考文献《算法分析与设计》 (C++描述)   清华大学出版社 石志国

    拥抱明天! 不给自己做枷锁去限制自己。 别让时代的悲哀,成为你人生的悲哀。
  • 相关阅读:
    查看文件方法、vim末行操作
    目录结构、文件管理命令
    计算机快捷键、常用命令、别名、
    Redis 使用与优化
    Redis-Sentinel
    Redis主从复制
    Redis持久化
    API的使用
    Redis安装和配置
    集群搭建(脑裂)
  • 原文地址:https://www.cnblogs.com/dd2hm/p/7221620.html
Copyright © 2011-2022 走看看