二叉查找树的相关操作

二叉查找树的相关操作

概述

  二叉查找树(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<<'\t';
        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;
}

输出

控制台输出结果

posted @ 2019-04-19 20:27  orion-orion  阅读(155)  评论(0编辑  收藏  举报