zoukankan      html  css  js  c++  java
  • 二叉排序/搜索/查找树

    二叉排序树(Binary Sort Tree)又称二叉查找树或二叉搜索树。 它或者是一棵空树;或者是具有下列性质的二叉树:
    (1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
    (2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
    (3)左、右子树也分别为二叉排序树。

    通俗地讲很简单:一句话就是左孩子比父节点小,右孩子比父节点大,还有一个特性就是”中序遍历“可以让结点有序。如下图:

    几种常见的操作:

    1、二叉树数据结构

    struct BSTNode
    {
        int data;        // value of node
        BSTNode *lchild; // left child of node
        BSTNode *rchild; // right child of node
    }BSTNode,*BSTree; 

    2、创建二叉排序树

    /* 递归建立二叉排序树 */
    void addBSTNode(BSTree &pCurrent,int value)//在这个函数中会要改变指针值,一定要记得使用引用传递
    {
        if (pCurrent==NULL)
        {
            BSTree pBSTree=new BSTNode();
            //BSTree pBSTree = (BSTree)malloc(sizeof(BSTNode));
            pBSTree->data=value;
            pBSTree->lchild=NULL;
            pBSTree->rchild=NULL;
            pCurrent=pBSTree;
        }
        else if (pCurrent->data<value)
            addBSTNode(pCurrent->rchild,value);
        else if (pCurrent->data>value)
            addBSTNode(pCurrent->lchild,value);
        else
            cout<<"node repeated"<<endl;
    }

    3、二叉排序树的插入(跟创建时操作一样,只是返回根节点),二叉查找树的插入过程如下:1.若当前的二叉查找树为空,则插入的元素为根节点,2.若插入的元素值小于根节点值,则将元素插入到左子树中,3.若插入的元素值不小于根节点值,则将元素插入到右子树中。首先找到插入的位置,要么向左,要么向右,直到找到空结点,即为插入位置,如果找到了相同值的结点,插入失败。 

    (1)递归版本:

    BSTree insert(BSTree root, int value)
    {
        BSTree pBSTree=new BSTNode();
        pBSTree->data=value;
        pBSTree->lchild=NULL;
        pBSTree->rchild=NULL;
        if(root==NULL){
            root=pBSTree;    
        }    
        else if(value<root->data)
            root->lchild=insert(root->lchild,value);    
        else
            root->rchild=insert(root->rchild,value);    
        return root;
    }

    (2)非递归版本:

    void insert_BST(BSTree q, int value)
    {
        BSTree p = new BSTNode();
        p->data = value;
        p->lchild = NULL;
        p->rchild = NULL;
        if(q == NULL){
            q = p;
            return ;    
        }        
        while(q->lchild != p && q->rchild != p){
            if(value < q->data){
                if(q->lchild){
                    q = q->lchild;    
                }    
                else{
                    q->lchild = p;
                }        
            }    
            else{
                if(q->rchild){
                    q = q->rchild;    
                }    
                else{
                    q->rchild = p;    
                }
            }
        }
        return;
    }

    4、二叉排序树的删除

    二叉查找树的删除,分三种情况进行处理:
    1.p为叶子节点,直接删除该节点,再修改其父节点的指针(注意分是根节点和不是根节点),如图a。
    2.p为单支节点(即只有左子树或右子树)。让p的子树与p的父亲节点相连,删除p即可;(注意分是根节点和不是根节点);如图b。
    3.有两个孩子的情况,当前结点与左子树中最大的元素交换,然后删除当前结点。左子树最大的元素一定是叶子结点,交换后,当前结点即为叶子结点,删除参考没有孩子的情况。另一种方法是,当前结点与右子树中最小的元素交换,然后删除当前结点。如图c。

    bool bst_delete(BSTree &node, int value) {
      BSTree parent = NULL;
      BSTree tmp;
      while(node != NULL) {
        if(value < node->data) { // 向左 
          parent = node;
          node = node->lchild;
        }
        else if(value > node->data) { // 向右 
          parent = node;
          node = node->rchild;
        }
        else { // 找到了 
          if(NULL==node->lchild && NULL==node->rchild) { // 叶子结点         
            if(parent == NULL) { // 根结点 
              delete node;
              node = NULL;
            }
            else { // 非根结点 
              (parent->lchild==node)?(parent->lchild=NULL):(parent->rchild=NULL);
              delete node;
              node = NULL;
            }        
          }
          else if(NULL!=node->lchild && NULL==node->rchild) { // 只有左孩子
            if(parent == NULL) { // 根结点 
              tmp = node;
              node = node->lchild;
              delete tmp;          
            }
            else { // 非根结点 
              (parent->lchild==node)?(parent->lchild=node->lchild):(parent->rchild=node->lchild);
              delete node;
            }
          }
          else if(NULL!=node->rchild && NULL==node->lchild) { // 只有右孩子 
            if(parent == NULL) { // 根结点 
              tmp = node;
              node = node->rchild;
              delete tmp;          
            }
            else { // 非根结点 
              (parent->lchild==node)?(parent->lchild=node->rchild):(parent->rchild=node->rchild);
              delete node;
            }
          }
          else { // 既有左孩子也有右孩子 
            BSTree leftNode = node;
            while(leftNode->rchild != NULL) {
              parent = leftNode;
              leftNode = leftNode->rchild;
            }
            // 交换leftNode与node
            int swapValue = leftNode->data;
            leftNode->data = node->data;
            node->data = swapValue;
            // 删除leftNode,parent肯定不为空 
            (parent->lchild==node)?(parent->lchild=NULL):(parent->rchild=NULL);
            delete node;
          }
        }
      }
      return false; // 失败
    }

    (3)二叉排序树的查找

    这个比较简单,要么找到了,要么向左,要么向右。

    BSTree bst_search(BSTree node, int value) {
      while(node != NULL) {
        if(value < node->data) // 向左 
          node = node->lchild;
        else if(value > node->data) // 向右 
          node = node->rchild;
        else // 找到 
          return node;
      }
      return NULL; // 失败 
    }

    主函数测试代码:

    int main()
    {
        BSTree pRoot=NULL; 
        int a[7];
        for(int i=0;i<7;i++)
        {
            cin>>a[i];
            addBSTNode(pRoot,a[i]);
        }
        //各种函数测试... 
        system("pause");
        return 0;
    }
  • 相关阅读:
    Android Studio同时监听多个Button实现activity跳转
    Android Studio--Activity实现跳转功能
    Gym 101170F Free Weights(二分)题解
    Gym 101170I Iron and Coal(BFS + 思维)题解
    Gym 101128F Landscaping(网络流)题解
    Gym 101128A Promotions(思维 + dfs)题解
    Gym 101480I Ice Igloos(思维乱搞)题解
    Gym 101480F Frightful Formula(待定系数)题解
    Gym 101128J Saint John Festival(凸包 + 二分判点和凸包关系)题解
    CodeForces 348D Turtles(LGV定理)题解
  • 原文地址:https://www.cnblogs.com/sooner/p/3028718.html
Copyright © 2011-2022 走看看