Binary Search Tree

Node *insert / delete (Node *root, int key) 

通过返回 Node * 来insert和delete。注意都要 root = insert / delete (root, key),否则bst为空insert第一个元素,或者删除掉最后一个元素的时候,root指针指向的位置会出现问题。

时间复杂度都是 O(h),h为二叉树的高度。

struct Node{
    int val;
    Node *left, *right;
    Node(int v):val(v),left(NULL),right(NULL){}
};

class BST{
private:
    Node *root;
    
    Node *insert(Node *root, int key){
        if (root==NULL) return new Node(key);
        // do not allow duplicates
        if (key < root->val)
            root->left = insert(root->left,key);
        else if (key > root->val)
            root->right = insert(root->right, key);
        return root;
    };
    
    bool search(Node *root, int key){
        if (root==NULL) return false;
        if (key<root->val) return search(root->left,key);
        else if (key>root->val) return search(root->right,key);
        return true;
    }
    
    Node *deleteNode(Node *root, int key){
        if (root==NULL) return NULL;
        if (key<root->val)
            root->left = deleteNode(root->left,key);
        else if (key>root->val)
            root->right = deleteNode(root->right,key);
        else{ // key==root->val
            if (root->left==NULL && root->right==NULL){ // delete this leaf node
                delete root;
                return NULL;
            }else if (root->left==NULL || root->right==NULL){
                Node *new_root=root->left?root->left:root->right;
                root->left = root->right = NULL;
                delete root;
                return new_root;
            }else{
                // find inorder successor
                Node *p=root->right;
                while (p->left) p=p->left;
                root->val = p->val;
                root->right = deleteNode(root->right,p->val);
            }
        }
        return root;
    }
    
    void inOrder(Node *root){
        if (root==NULL) return;
        inOrder(root->left);
        cout << root->val << ' ';
        inOrder(root->right);
    }
    
public:
    BST():root(NULL){}
    void insert(int key){root=insert(root,key);}
    bool search(int key){return search(root,key);}
    void deleteNode(int key){root=deleteNode(root,key);}
    void inOrder(){inOrder(root);}
};

int main() {
    BST bst;
    bst.insert(50);
    bst.insert(30); 
    bst.insert(20); 
    bst.insert(40); 
    bst.insert(70); 
    bst.insert(60); 
    bst.insert(80); 
    
    cout<<bst.search(28)<<endl;
    cout<<bst.search(20)<<endl;
    
    bst.inOrder(); cout<<endl;
    
    bst.deleteNode(20);
    bst.inOrder(); cout<<endl;
    
    bst.deleteNode(30);
    bst.inOrder(); cout<<endl;
    
    bst.deleteNode(50);
    bst.inOrder(); cout<<endl;
    return 0;
}

 

void insert / delete (Node *&root, int key) 

对指针的引用,效率比上述方法高。以下代码是之前数据结构课本代码:

#include <iostream>
using namespace std;

template <class Type>
class BinarySearchTree{
    private:
        struct node{
            node *left, *right; //结点的左、右儿子的地址
            Type data; //结点的数据信息
            node(const Type &x, node *L=NULL, node *R=NULL):data(x),left(L),right(R){}
            ~node(){}
        };    
        node *root; //二叉树的根结点
        
        bool find(const Type &x, node *t) const;
        void insert(const Type &x, node *&t);
        void remove(const Type &x, node *&t);
        void clear(node *&t);
        
    public:
        BinarySearchTree(node *t=NULL){root=t;}
        ~BinarySearchTree(){clear(root);} 
        bool search(const Type &x) const; //非递归 
        bool find(const Type &x) const{return find(x,root);}
        void insert(const Type &x){insert(x,root);}
        void remove(const Type &x){remove(x,root);}
}; 

template <class Type>
bool BinarySearchTree<Type>::search(const Type &x) const{
    node *t=root;
    while(t!=NULL){
        if(x==t->data) return true;
        else if(x>t->data) t=t->right;
        else t=t->left;
    }
    return false;
} 

template <class Type>
bool BinarySearchTree<Type>::find(const Type &x, node *t) const{
    if(t==NULL) return false;
    if(x<t->data) return find(x,t->left);
    else if(x>t->data) return find(x,t->right);
    else return true;
} 

template <class Type>
void BinarySearchTree<Type>::insert(const Type &x, node *&t){
    if(t==NULL) t=new node(x);
    else if(x<t->data) insert(x,t->left);
    else insert(x,t->right);
} 

template <class Type>
void BinarySearchTree<Type>::remove(const Type &x, node *&t){
    if(t==NULL) return;
    if(x<t->data) remove(x,t->left);
    else if(x>t->data) remove(x,t->right);
    else{ //找到了 删除 
        if((t->left==NULL)&&(t->right==NULL)){ //是叶子节点 直接删除 
            delete t;
            t = NULL;
        }else if((t->left!=NULL)&&(t->right!=NULL)){ //有两个儿子
            node *tmp=t->left;
            while(tmp->right) tmp=tmp->right;
            t->data = tmp->data;
            remove(tmp->data, t->left); //直接删tmp会有问题 tmp是通过while得到的 不是通过递归得到的 删除以后无法链接 
        }else{ //只有一个儿子 (其实叶子结点的情况也可以并进来) 
            node *tmp=t;
            t = (t->left!=NULL)?t->left:t->right;
            delete tmp;
        } 
    }
} 

template<class elemType>
void BinarySearchTree<elemType>::clear(node *&t){ 
    if (t!=NULL){
        clear(t->left); 
           clear(t->right);
           delete t;
    } 
    t = NULL;
}


int main(){
    int a[]={10,8,6,21,87,56,4,0,11,3,22,7,5,34,1,2,9};
    BinarySearchTree<int> tree;
    for(int i=0;i<17;++i) tree.insert(a[i]);
    cout << tree.find(2) << endl;
    tree.remove(2);
    cout << tree.find(56) << endl;
    return 0;
} 

 

Reference

https://www.geeksforgeeks.org/binary-search-tree-set-1-search-and-insertion/

https://www.geeksforgeeks.org/binary-search-tree-set-2-delete/

https://www.gormanalysis.com/blog/making-a-binary-search-tree-in-cpp/

posted @ 2019-10-12 13:49  約束の空  阅读(125)  评论(0)    收藏  举报