二叉搜索树(BST)递归与非递归的插入、删除、查找的实现

昨天碰到了二叉搜索树(BST)这种数据结构,索性详细的学习了一遍。

BST的定义:
如果一棵树的左子树不为空,那么其所有节点的值均小于其根结点的值,如果右子树不为空,那么其所有节点的值均大于其根结点的值,它的左右子树也满足如上性质。空树也是BST。

我的BST的实现是以没有重复元素为前提,其实有重复元素也无大碍,只是把实现过程中相关的<改成<=即可,

节点结构定义:

class Node{
public:
    int val;
    Node *left, *right;
    Node() {}
    Node(int val) : val(val), left(NULL), right(NULL) {}
};

BST结构定义及实现方法:

class BST{
private:
    Node *root;
    void Recursion_Insert_Node(Node *&node, int x);//递归插入结点
    void Non_Recursion_Insert_Node(Node **node, int x);//非递归插入结点
    Node *Recursion_Find_Node(Node *node, int x);//递归查找结点
    Node *Non_Recursion_Find_Node(Node *root, int x);//非递归查找结点
    void Delete_Node(Node **root, int x);//删除结点
    void preOrder_Traverse(Node *root);//前序遍历
    void inOrder_Traverse(Node *root);//中序遍历
    void postOrder_Traversal(Node *root);//后序遍历
    void Delete_BST(Node *node);//释放空间
public:
    BST();
    ~BST();
    void Create_BST(int *num, int n);//创建BST
    Node *Find_Node(int x);
    void Delete_Node(int x);
    void preOrder_Traverse();
    void inOrder_Traverse();
    void postOrder_Traversal();
};

让我们首先来看看插入结点是如何实现的:
对于第一个要存入的值,我们将它设置为根结点,然后对于小于根结点的值,我们将其移动到左子树上再进行比较,直到移动到成为叶子节点即可,大于根结点的值同理。

具体实现:

递归:

void BST::Recursion_Insert_Node(Node *&node, int x){
    if(node == NULL){
        node = new Node(x);
    }
    else if(node->val > x){
        Recursion_Insert_Node(node->left, x);
    }
    else if(node->val < x){
        Recursion_Insert_Node(node->right, x);
    }
}

非递归:

void BST::Non_Recursion_Insert_Node(Node **root, int x){
    Node *p = *root;
    Node *fa = *root;
    while(p){
        if(p->val == x){
            printf("%d is already exist!\n", x);
            return;
        }
        fa = p;
        if(p->val > x){
            p = p->left;
        }
        else{
            p = p->right;
        }
    }
    if(fa == NULL){
        *root = new Node(x);
    }
    else if(fa->val > x){
        fa->left = new Node(x);
    }
    else{
        fa->right = new Node(x);
    }
}

注意对于非递归的情况,Node的类型为指向指针的指针,不能单单传指针,这是因为如果只传指针,形参为指针值的拷贝,当root指向NULL的时候,在函数内部new的节点并不会被实际的指针指到。还有用指针的引用也不行,因为这样会使得指向根结点的指针指向其子节点。

对于查找结点的实现:
思想和插入的一样,只是可以使用指针,而不用指向指针的指针,因为我们只需要找到所查找元素的地址,并不需要对其操作,使用指针可以很轻松的完成工作。

递归:

Node *BST::Recursion_Find_Node(Node *node, int x){
    if(node == NULL)
        return NULL;
    if(node->val == x)
        return node;
    if(node->val > x)
        return Recursion_Find_Node(node->left, x);
    else
        return Recursion_Find_Node(node->right, x);
}

非递归:

Node *BST::Non_Recursion_Find_Node(Node *node, int x){
    if(node == NULL)
        return NULL;
    while(node){
        if(node->val == x)
            return node;
        else if(node->val > x)
            node = node->left;
        else
            node = node->right;
    }
    return node;
}

最后就是删除操作了:

删除操作实在是想不出递归写法。。。

对于BST的删除操作,有三种情况:

1:删除节点恰好为叶子节点
这种情况最好处理,只需要将其父节点指向空,然后delete该节点即可。

2:删除节点恰好有一个分支
我们只需要将其父亲节点指向其儿子节点即可,然后delete掉它,也比较简单。

3:删除节点恰好有两个分支
这种情况比较麻烦,有两种处理方法,在说这两种方法之前我们首先要知道两个概念:
节点的前驱:小于该节点的最大节点,前驱没有右子树
节点的后继:大于该节点的最小节点,后继没有左子树
了解后我们就可以阐述方法了:
第一种方法就是找到该节点的前驱,然后将它的值赋值给要删除的节点,最后删除这个前驱即可。第二种方法和第一种类似,就是找到该节点的后继,然后将它的值赋值给要删除的节点,最后删除这个后继即可。这里会用到前驱没有右子树,后继没有左子树的特性,具体实现看代码吧。

void BST::Delete_Node(Node **root, int x){
    Node *p = *root;
    Node *fa = *root;
    while(p){
        if(p->val == x){
            break;
        }
        fa = p;
        if(p->val > x){
            p = p->left;
        }
        else{
            p = p->right;
        }
    }
    if(p == NULL){
        printf("%d is not found!\n", x);
        return;
    }
    if(p->left == NULL && p->right == NULL){//若p为叶子结点
        if(p == *root){//p为根结点
            *root = NULL;
        }
        else if(fa->left == p){
            fa->left = NULL;
        }
        else{
            fa->right = NULL;
        }
        delete p;
    }
    else if(p->left == NULL || p->right == NULL){//若p为单支结点
        if(p == *root){
            if(p->left != NULL){
                *root = p->left;
            }
            else{
                *root = p->right;
            }
        }
        else{
            if(fa->left == p){
                if(p->left != NULL){
                    fa->left = p->left;
                }
                else{
                    fa->left = p->right;
                }
            }
            else{
                if(p->left != NULL){
                    fa->right = p->left;
                }
                else{
                    fa->right = p->right;
                }
            }
        }
        delete p;
    }
    else{//若p为双支结点
        Node *parent = p;
        Node *child = p->right;
        while(child->left){
            parent = child;
            child = child->left;
        }
        p->val = child->val;
        if(parent == p){
            p->right = child->right;
        }
        else{
            parent->left = child->right;
        }
        delete child;
    }
}

程序总览:

#include <cstdio>
using namespace std;

class Node{
public:
    int val;
    Node *left, *right;
    Node() {}
    Node(int val) : val(val), left(NULL), right(NULL) {}
};

class BST{
private:
    Node *root;
    void Recursion_Insert_Node(Node *&node, int x);//递归插入结点
    void Non_Recursion_Insert_Node(Node **node, int x);//非递归插入结点
    Node *Recursion_Find_Node(Node *node, int x);//递归查找结点
    Node *Non_Recursion_Find_Node(Node *root, int x);//非递归查找结点
    void Delete_Node(Node **root, int x);//删除结点
    void preOrder_Traverse(Node *root);//前序遍历
    void inOrder_Traverse(Node *root);//中序遍历
    void postOrder_Traversal(Node *root);//后序遍历
    void Delete_BST(Node *node);//释放空间
public:
    BST();
    ~BST();
    void Create_BST(int *num, int n);//创建BST
    Node *Find_Node(int x);
    void Delete_Node(int x);
    void preOrder_Traverse();
    void inOrder_Traverse();
    void postOrder_Traversal();
};

BST::BST(){
    this->root = NULL;
}

void BST::Create_BST(int *num, int n){
    for(int i = 0; i < n; i++){
        // Recursion_Insert_Node(this->root, num[i]);
        Non_Recursion_Insert_Node(&this->root, num[i]);
    }
}

void BST::Recursion_Insert_Node(Node *&node, int x){
    if(node == NULL){
        node = new Node(x);
    }
    else if(node->val > x){
        Recursion_Insert_Node(node->left, x);
    }
    else if(node->val < x){
        Recursion_Insert_Node(node->right, x);
    }
}

void BST::Non_Recursion_Insert_Node(Node **root, int x){
    Node *p = *root;
    Node *fa = *root;
    while(p){
        if(p->val == x){
            printf("%d is already exist!\n", x);
            return;
        }
        fa = p;
        if(p->val > x){
            p = p->left;
        }
        else{
            p = p->right;
        }
    }
    if(fa == NULL){
        *root = new Node(x);
    }
    else if(fa->val > x){
        fa->left = new Node(x);
    }
    else{
        fa->right = new Node(x);
    }
}

void BST::Delete_Node(int x){
    Delete_Node(&this->root, x);
}

void BST::Delete_Node(Node **root, int x){
    Node *p = *root;
    Node *fa = *root;
    while(p){
        if(p->val == x){
            break;
        }
        fa = p;
        if(p->val > x){
            p = p->left;
        }
        else{
            p = p->right;
        }
    }
    if(p == NULL){
        printf("%d is not found!\n", x);
        return;
    }
    if(p->left == NULL && p->right == NULL){//若p为叶子结点
        if(p == *root){//p为根结点
            *root = NULL;
        }
        else if(fa->left == p){
            fa->left = NULL;
        }
        else{
            fa->right = NULL;
        }
        delete p;
    }
    else if(p->left == NULL || p->right == NULL){//若p为单支结点
        if(p == *root){
            if(p->left != NULL){
                *root = p->left;
            }
            else{
                *root = p->right;
            }
        }
        else{
            if(fa->left == p){
                if(p->left != NULL){
                    fa->left = p->left;
                }
                else{
                    fa->left = p->right;
                }
            }
            else{
                if(p->left != NULL){
                    fa->right = p->left;
                }
                else{
                    fa->right = p->right;
                }
            }
        }
        delete p;
    }
    else{//若p为双支结点
        Node *parent = p;
        Node *child = p->right;
        while(child->left){
            parent = child;
            child = child->left;
        }
        p->val = child->val;
        if(parent == p){
            p->right = child->right;
        }
        else{
            parent->left = child->right;
        }
        delete child;
    }
}

Node *BST::Find_Node(int x){
    // return Recursion_Find_Node(this->root, x);
    return Non_Recursion_Find_Node(this->root, x);
}

void BST::preOrder_Traverse(){
    preOrder_Traverse(this->root);
}

void BST::inOrder_Traverse(){
    inOrder_Traverse(this->root);
}

void BST::postOrder_Traversal(){
    postOrder_Traversal(this->root);
}

Node *BST::Recursion_Find_Node(Node *node, int x){
    if(node == NULL)
        return NULL;
    if(node->val == x)
        return node;
    if(node->val > x)
        return Recursion_Find_Node(node->left, x);
    else
        return Recursion_Find_Node(node->right, x);
}

Node *BST::Non_Recursion_Find_Node(Node *node, int x){
    if(node == NULL)
        return NULL;
    while(node){
        if(node->val == x)
            return node;
        else if(node->val > x)
            node = node->left;
        else
            node = node->right;
    }
    return node;
}

void BST::preOrder_Traverse(Node *root){
    if(root != NULL){
        printf("%d ", root->val);
        preOrder_Traverse(root->left);
        preOrder_Traverse(root->right);
    }
}

void BST::inOrder_Traverse(Node *root){
    if(root != NULL){
        inOrder_Traverse(root->left);
        printf("%d ", root->val);
        inOrder_Traverse(root->right);
    }
}

void BST::postOrder_Traversal(Node *root){
    if(root != NULL){
        postOrder_Traversal(root->left);
        postOrder_Traversal(root->right);
        printf("%d ", root->val);
    }
}

void BST::Delete_BST(Node *node){
    if(node == NULL)
        return;
    if(node->left != NULL)
        Delete_BST(node->left);
    if(node->right != NULL)
        Delete_BST(node->right);
    delete node;
}

BST::~BST(){
    Delete_BST(this->root);
}

int main()
{
    return 0;
}

代码什么的就不要吐槽了T T

    原文作者:二叉查找树
    原文地址: https://blog.csdn.net/s_h_r/article/details/50790541
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞