HomeWork——Binary Search Tree

来源:互联网 发布:网络电影疯狂小镇 编辑:程序博客网 时间:2024/06/12 01:01

本次作业是建立一个Binary Search Tree,二叉搜索树。

二叉搜索树,也叫做排序二叉树,它具有如下性质:若它的左树不为空,则左树上所有节点的值均小于它的根节点值;若它的右子树不空,则右树上所有节点的值均大于它的根节点的值,它的左右子树有分别为二叉搜索树。


首先我们应设置节点的结构:

struct Node{

int val;

Node* left;

Node* right;

Node(int v, Node* l = NULL, Node* r = NULL) : val(v), left(l), right(r) {}

};


接着设计一个Binary Search Tree的类

  1. classBinarySearchTree {
  2. public:
  3. structNode {
  4. int val;
  5. Node* left;
  6. Node* right;
  7. Node(int v,Node* l= NULL,Node* r= NULL):
  8. val(v), left(l), right(r){
  9. }
  10. };
  11.  
  12. BinarySearchTree();
  13. BinarySearchTree(const std::vector<int>&);
  14. ~BinarySearchTree();
  15.  
  16. bool insertNode(int);
  17. bool searchNode(int);
  18. bool deleteNode(int);
  19. void clear();
  20.  
  21. Node* getRoot()const;
  22.  
  23. private:
  24. Node* root;
  25. };

缺省构造函数则令root = NULL即可。

传入vector构造二叉搜索树函数则利用中序插入方法建立,即使用insertNode函数将vector中的元素一个个插入即可。

析构函数使用clear()函数即可。

而clear()函数这里我利用了STL的queue容器适配器来进行树的删除,其中用到的算法为BFS:
void BinarySearchTree::clear() {
    queue<Node*> que;
    if (root != NULL) {
        que.push(root);
    }
    while (!que.empty()) {
        Node* temp = que.front();
        que.pop();
        if (temp->left != NULL) {
            que.push(temp->left);
        }
        if (temp->right != NULL) {
            que.push(temp->right);
        }
        delete temp;
    }
}

bool insertNode(int value)函数利用了递归的思想,相等则不插入,小于节点值判断左边是否为空,为空建立新节点,不为空则递归左边的节点。大于当前节点的值亦然。

bool BinarySearchTree::insertNode(int value) {
    Node* temp = root;
    if (temp == NULL) {
        temp = new Node(value);
        root = temp;
        return true;
    }
    while (temp != NULL) {
        if (temp->val == value) {
            return false;
        } else if (temp->val > value) {
            if (temp->left == NULL) {
                temp->left = new Node(value);
                return true;
            } else {
                temp = temp->left;
            }
        } else {
            if (temp->right == NULL) {
                temp->right = new Node(value);
                return true;
            } else {
                temp = temp->right;
            }
        }
    }
    return false;
}

查找函数非常简单:


bool BinarySearchTree::searchNode(int value) {
    Node* temp = root;
    while (temp != NULL) {
        if (temp->val == value) {
            return true;
        } else if (temp->val > value) {
            temp = temp->left;
        } else {
            temp = temp->right;
        }
    }
    return false;
}


最后重点是删除节点的函数,这是本题的关键,因为删除的节点的左右儿子决定了删除节点的方法,一共有三种情况:

1,如果要删除的节点没有左右儿子,则直接删除即可,并前驱设为NULL

2,如果要删除的节点只有左儿子或者右儿子,先标记该节点的前驱和后继,之后删除该节点,并将该节点的后继接到该节点的前驱上。

3,如果要删除的节点既有左儿子也有右儿子,则可以找该节点的左树中值最大的节点或者右树值最小的节点。比如找左树值最大的节点,则将该节点的值与替换要删除的节点的值,标记这个左树最大值节点的前驱和后继,删除这个左树最大值得节点,并将这个左树最大值的节点的后继(如果存在),接到刚刚标记的前驱上面。(注意如果要删除的节点的左树只有一个节点则要另外考虑这种情况)。


下面是该算法的实现:


bool BinarySearchTree::deleteNode(int value) {
    Node* temp = root;
    Node* parent = root;
    while (temp != NULL) {
        if (temp->val == value) {
            if (temp->left == NULL && temp->right == NULL) {
                if (parent->left == temp) {
                    parent->left = NULL;
                } else {
                    parent->right = NULL;
                }
                delete temp;
            } else if (temp->left == NULL) {
                if (parent->left == temp) {
                    parent->left = temp->right;
                } else {
                    parent->right = temp->right;
                }
                delete temp;
            } else if (temp->right == NULL) {
                if (parent->left == temp) {
                    parent->left = temp->left;
                } else {
                    parent->right = temp->left;
                }
                delete temp;
            } else {
                Node* s = temp->left;
                Node* q = temp;
                while (s->right != NULL) {
                    q = s;
                    s = s->right;
                }
                temp->val = s->val;
                if (q != temp) {
                    q->right = s->left;
                } else {
                    q->left = s->left;
                }
            }
            return true;
        } else if (temp->val > value) {
            parent = temp;
            temp = temp->left;
        } else {
            parent = temp;
            temp = temp->right;
        }
    }
    return false;
}


0 0
原创粉丝点击