zoukankan      html  css  js  c++  java
  • 查找

    线性表的查找

    <1>顺序查找

    <2>二分查找

    递归算法
    typedef struct
    {
        KeyType key;
        InfoType otherinfo; //此类型依赖于应用
    }NodeType;
    typedef NodeType SeqList[n]; 
    int BinSearch(SeqList R, int low, int high, KeyType K)
    {     //在有序表R[low,high]中进行二分查找,成功时返回结点的位置,失败时返回零
        int min;
        if(low<=high){   //当前查找区间R[low..high]非空
        {
            mid=(low+high)/2;//置当前查找区间上、下界的中值
            if(R[mid].key==K) return mid; //查找成功返回
            else if(R[mid].kdy>K)
                return BinSearch(R,low,mid-1,K); //继续在R[low..mid-1]中查找
            else
                return BinSearch(R,low,mid-1,K); //继续在R[mid+1..high]中查找
         }
         return -1; //当low>high时表示查找区间为空,查找失败
    } //BinSeareh
    
    非递归查找法
    int BinSearch(SeqList R,KeyType K)
    { //在有序表R[1..n]中进行二分查找,成功时返回结点的位置,失败时返回零
        int low=1,high=n,mid; //置当前查找区间上、下界的初值
        while(low<=high)
        { //当前查找区间R[low..high]非空
            mid=(low+high)/2;
            if(R[mid].key==K) return mid; //查找成功返回
            if(R[mid].kdy>K)    high=mid-1; //继续在R[low..mid-1]中查找
            else    low=mid+1; //继续在R[mid+1..high]中查找
        }
        return 0; //当low>high时表示查找区间为空,查找失败
    } //BinSeareh

    二叉排序树

    <1>二叉排序树的定义(其中的关键字不重复)

    要么是空树,要么满足如下条件(BST性质):每个节点的左子树上所有节点的值均小于该节点的值,右子树上所有节点的值均大于等于该节点的值; 

    typedef int KeyType;      //假定关键字类型为整数
    typedef struct BiTNode
    {
        KeyType key;          //关键字项
        InfoType otherinfo;   //其它数据域,InfoType视应用情况而定,下面不处理它
        struct BiTNode *lchild, *rchild;
    }BiTNode, *BiTree;

    <2>二叉排序树的查找

    /* 递归查找二叉排序树T中是否存在key, */
    /* 指针f指向T的双亲,其初始调用值为NULL */
    /* 若查找成功,则指针p指向该数据元素结点,并返回TRUE;*/
    /* 若查找不成功,指针p指向查找路径上访问的最后一个结点并返回FALSE,这样方便后续插入节点,若p为null则表示该树为空。
    */ Status SearchBST(BiTree T, KeyType key, BiTree f, BiTree *p) { if (T == NULL) /* 若输入的节点为空,则查找不成功 */ { *p = f; return FALSE; } else if (key == T->key) /* 查找成功 */ { *p = T; return TRUE; } else if (key < T->key) return SearchBST(T->lchild, key, T, p); /* 在左子树中继续查找 */ else return SearchBST(T->rchild, key, T, p); /* 在右子树中继续查找 */ }

    <3>二叉排序树的插入插入算法:查找关键字key,若查找成功,则不用插入。若查找失败,p为null,或则为要插入的节点的双亲节点。 

    /*  当二叉排序树T中不存在关键字等于key的数据元素时,插入key并返回TRUE,否则返回FALSE */
    Status InsertBST(BiTree *T, KeyType key) 
    {  
        BiTree p,s;
    
        if (SearchBST(*T, key, NULL, &p)) /*  查找成功,则树中已有关键字相同的结点,不再插入 */
            return FALSE;  
        
        /* 查找不成功 */
        s = (BiTree)malloc(sizeof(BiTNode));
        s->data = key;  
        s->lchild = s->rchild = NULL;  
        if (!p) 
            *T = s;            /*  插入s为新的根结点 */
        else if (key < p->key) 
            p->lchild = s;    /*  插入s为左孩子 */
        else 
            p->rchild = s;  /*  插入s为右孩子 */
        
        return TRUE;         
    }

    <4>删除节点(不改变二叉排序树的BST性质),分三种情况:
    a,*p是叶子节点,无须连接*p的子树,只需将*p的双亲*parent中指向*p的指针域置空即可。
    b,*p只有一个孩子*child只需将*child和*p的双亲直接连接后,即可删去*p。有四种情况,*p是否为根节点,*child为左或右孩子。具体【参见动画演示

    c,*p有两个孩子,先令q=p,将被删结点的地址保存在q中;然后找*q的中序后继*p,并在查找过程中仍用parent记住*p的双亲位置。*q的中序后继*p一定是*q的右子树中最左下的结点,它无左子树。因此,可以将删去*q的操作转换为删去的*p的操作,即在释放结点*p之前将其数据复制到*q中,就相当于删去了*q。具体【参见动画演示】。

    /*在二叉排序树*Tptr中删去关键字为key的结点*/
    Status DeleteBST(BiTree *T, KeyType key)
    {
        BiTree parent=NULL, p=*T;   //用p指向要删除的节点,parent指向*p的双亲
        BiTree q, child;            
        while(p)                   //从根开始查找关键字为key的待删结点
        { 
            if(p->key == key)     
                break;
            parent = p;           
            p = (key < p->key)? p->lchild:p->rchild;   //在p的左或右子树中继续找
        }
    
        if(p == NULL)     //找不到被删结点则返回FALSE
            return FALSE;   
        
        /*  将情况(3)转换为情况(2),而情况(1)相当于是情况(2)中child=NULL的状况,
        q保存被删节点的地址,找到*q的中序后继*p(或中序前继),
        *p属于(1)(2)情况,然后将后继节点的数据复制到*q节点,接上后继节点的子树后删除该节点*/
        q = p;              
        if(q->lchild && q->rchild)   
          for(parent=p, p=p->rchild; p->lchild; parent=p, p=p->lchild);
             
        child = (p->rchild)? p->rchild:p->lchild;       //若是情况(2),则child非空;否则child为空
        
        if(parent == NULL)  //说明*p属于(1)(2),且*p为根节点,删除*p后应修改根指针
            *T = child; 
        else                //属于(1)(2)且p不是根节点或属于情况(3),删除后不用修改根指针
        { 
            /*  删除*p,*p的孩子和*p的双亲进行连接  */
            if(p == parent->lchild) 
                parent->lchild=child; 
            else 
                parent->rchild = child; 
            
            /*  情况(3)需将*p的数据复制到*q,若还有其它数据域亦需复制  */
            if(p != q) 
                q->key = p->key;    
        } //endif
    
        free(p); 
        return TURE;
    } 

     

  • 相关阅读:
    《入门经典》——6.15
    《Linear Algebra and Its Application》-chaper1-行化简法解决线性方程组
    《算法实战策略》-chaper19-队列、栈和双端队列
    《Linear Algebra and Its Applications》-chaper1-向量方程、矩阵方程和线性方程组
    辛普森法则
    《训练指南》——6.15
    《入门经典》——6.21
    《算法问题实战策略》-chaper13-数值分析
    Scheme 中的 pair 和 list 简述
    C. Friends
  • 原文地址:https://www.cnblogs.com/zhoutian220/p/4064494.html
Copyright © 2011-2022 走看看