zoukankan      html  css  js  c++  java
  • 二叉查找树的相关操作

    二叉查找树的相关操作

    概述

      二叉查找树(Binary Search Tree)是一种非常重要的数据结构。它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
      二叉查找树的操作包括创建,插入节点,遍历,删除节点等。其中删除节点是其中较为麻烦的操作,故一下着重讨论它的节点删除算法。

    删除节点算法图解

    1.我们现在有一棵二叉查找树。很容易发现,它的中序遍历数组{2.3.4.5.6.8.9}具有递增的性质。

    初始二叉树
    2.我们这里演示删除5节点,也就是该二叉树的根结点。那么问题来了,删除了这个节点,我们用哪个节点来顶替它才能继续保持二叉查找树的性质呢?顶替它的节点应当是值和它最相近的节点,即中序遍历时在该节点前一个遍历的节点或后一个遍历的节点。观察中序遍历数组可知,这两个节点就是和5节点相邻的4节点和6节点。我们这里决定选6节点顶替它。我们可以编写一个Findmin函数在5节点的右子树中查找最小的节点(6节点),并返回6节点的位置。
    查找顶替的节点
    3.找到“顶替结点”(6节点)的位置了,我们可以将"顶替节点”的值赋给待删除的5节点,以替换掉待删除的节点。完成该步操作后,中序遍历数组为{2,3,4,6,6,8,9}
    替换掉要删除的节点
    4.接着,我们只需要把顶替节点删除即可。至此,删除节点操作正式完成。最终中序遍历数组为{2,3,4,6,8,9}
    删除顶替节点

    代码

    1.节点类的声明:

    struct TreeNode{
        int val;
        TreeNode* left;
        TreeNode* right;
        TreeNode(int x=0):val(x),left(NULL),right(NULL) {}
    };
    

    2.二叉树类的声明,类的方法包括3个用于插入,删除和遍历的对外接口以及实现这些操作的成员函数。

    struct BST{
        TreeNode* root;
        //构造函数
        BST():root(NULL) {}
        //析构函数
        ~BST();
    
        //供外部调用的接口
        void insert(int x);
        void Delete(int x);
        void inordertravaerse();
    
        private: //供内部调用的方法
        void clear(TreeNode* &root);
        void insertnode(int x,TreeNode* &root);
        void deletenode(int x,TreeNode* &node);
        /*找到在二叉排序树中比x大的最小的点
        即在二叉排序树的中序遍历中刚好位于x右边的点*/
        TreeNode* findmin(TreeNode* node);
        //查找元素值为x的节点,返回节点指针
        TreeNode* findnode(int x,TreeNode* root);
    };
    

    3.二叉树析构函数的驱动程序及其实现函数

    BST::~BST(){
        clear(root);
    }
    void BST::clear(TreeNode* &root){
        if(root==NULL) return;
        else{
            clear(root->left);
            clear(root->right);
            delete(root);
        }
        root=NULL;
    }
    
    

    3.二叉树插入节点的对外接口及其实现函数

    void BST::insert(int x){
        insertnode(x,root);
    }
    
    void BST::insertnode(int x,TreeNode* &root){
        if(root==NULL){
            root=new TreeNode(x);
        }
        else{
            if(x<root->val){
                insertnode(x,root->left);
            }
            else{
                insertnode(x,root->right);
            }
        }
        return;
    }
    

    4.二叉树删除节点的对外接口及其实现函数

    void BST::Delete(int x){
        deletenode(x,root);
    }
    
    void BST::deletenode(int x,TreeNode* &node){
        if(node==NULL) return;
        else if(node->val<x) deletenode(x,node->right);
        else if(node->val>x) deletenode(x,node->left);
        if(node->left&&node->right){
            //找到比cur的值大的最小的点,即中序遍历正好位于cur右边的节点
            node->val=findmin(node->right)->val;
            deletenode(node->val,node->right);
        }
      else{
          TreeNode* tmp=node;
          node=(node->left!=NULL)?node->left:node->right;
          delete(tmp);
      }
    }
    

    5.Findmin函数实现,查找“顶替节点”,即待删除节点右子树中最小的节点(中序遍历中在待删除节点之后遍历的节点),并返回其地址。

    TreeNode* BST::findmin(TreeNode* node){
        TreeNode* cur=node;
        while(cur->left){
            cur=cur->left;
        }
        return cur;
    }
    

    6.二叉树节点的查找函数,从根点开始递归地查找具有某个值的节点,并返回这个节点的地址。

    TreeNode* BST::findnode(int x,TreeNode* root){
        if(root==NULL) return NULL;//没有找到该节点,返回空指针
        else if(root->val==x){
            return root;
        }
        else{
            if(x<root->val){
                findnode(x,root->left);
            }
            else{
                findnode(x,root->right);
            }
        }
        return NULL;
    }
    

    7.二叉树的中序遍历函数,这里采用非递归方式遍历。

    void BST::inordertravaerse(){
        stack<TreeNode*> S;
        TreeNode* cur=root;
         while(cur||!S.empty()){
            while(cur){
                S.push(cur);
                cur=cur->left;
            }
            TreeNode* top=S.top();
            S.pop();
            cout<<top->val<<'	';
            cur=top->right;
        }
    }
    

    8.最后,用main函数进行功能测试。

    int main(){
        BST T;
        T.insert(5);
        T.insert(3);
        T.insert(8);
        T.insert(2);
        T.insert(4);
        T.insert(6);
        T.insert(9);
    
        cout<<"删除节点5之前的二叉查找树中序遍历如下"<<endl;
        T.inordertravaerse();
        cout<<endl;
    
        T.Delete(5);
    
        cout<<"删除节点5之后的二叉查找树中序遍历如下"<<endl;
        T.inordertravaerse();
        cout<<endl;
        
        system("pause");
        return 0;
    }
    

    输出

    控制台输出结果

  • 相关阅读:
    Objective-C method及相关方法分析
    java对象和json数据转换实现方式1-使用json-lib实现
    java中TCP传输协议
    【剑指Offer学习】【面试题27:二叉搜索树与双向链表】
    4.2.2 MINUS
    Hadoop for .NET Developers
    在命名空间下定义类型
    Android NDK课程录制完毕上线
    全然同态加密
    从golang的垃圾回收说起(下篇)
  • 原文地址:https://www.cnblogs.com/lonelyprince7/p/12247412.html
Copyright © 2011-2022 走看看