普通二叉排序树

1.二叉查找树(BST,Binary Search Tree)
注意和堆排序中的堆区分开。
参考我的博客,常见内排序算法中的堆排序
定义:1)如果左子树不空,那么左子树的所有节点均小于根节点
         2)如果右子树不空,那么右子树的所有节点均大于根节点
         3)左右子树也都是BST


1.1二叉查找树的查找
如何在二叉查找树上查找某个为key的节点?
首先比较key和根节点,如果其大小等于根节点,退出;
如果小于根节点,递归搜索左子树;
如果大于根节点,递归搜索右子树。

 

1.2如何在二叉查找树中插入一个节点
1)如果树上已经有关键字相等的节点,不插入
2)否则,要插入的节点,必定是叶子节点,利用1.1中的查找算法,查找不成功的最后一
个节点必然是要插入节点的父亲节点。然后判定要插入节点是该父亲节点的左孩子还是右孩子。

 

1.3如何在二叉查找树上删除一个节点
1)找到该节点d
2)删除该节点d并修改相应指针。
   我看严蔚敏老师那本树上搞的甚是复杂,我老婆比较厉害,帮我总结了个简单的,先看性质,再看图说话。
   性质:对于二叉排序树上的任意一个节点,如果它有子树,则有如下性质, 其左子树的最右侧子树的值是小于它的最大值,

   其右子树的最左侧子树的值是大于它的最小值,这个小于它的最大值和大于它的最小值都可以替代删除节点做根。我取左子树的最右侧

   子树。
   删除节点d,共有四种情况:

   1)d的左右子树均NULL,删除d,把d父亲节点的相应指针置NULL。

        提醒:注意图片2中的特殊情况,d没有父亲,删除d后,整个树为NULL。

 

 

 

                                  

                       图片1                                                                         图片2

 


   2)d的左子树不空,右子树NULL,删除d,把d的左子树链接到d的父亲节点。

        提醒:图片4中的特殊情况,d无父亲节点,删除d后,整个树的根需要变动,否则我们将失去树根。

        

                             

           图片3                                                                                图片4

 


   3)d的左子树NULL,右子树不空,删除d,把d的右子树链接到d的父亲节点

        提醒:图片6中的特殊情况,d无父亲节点,删除d后,整个树根要变动,否则我们将永远失去树根。

                            

                    图片5                                                                    图片6

 


   4)d有左子树和右子树,d转左子树,然后向右直到最右r,修改d的关键字为r的关键字,删除r,将r的左子树链接到r的父亲(r不可能有

        右子树

        

                                                             图片7       

 

 

1.4二叉查找树的宽度优先遍历
写这个功能,主要是为了测试上面1.1,1.2,1.3几个功能的实现是否正确,可以自己造几个
数据插入,然后调用我写的宽度优先遍历打印出来和自己手工画的做比较。
用了STL中的list做队列,没有自己写队列。

 

1.5二叉查找树的中序遍历
中序遍历的结果是一个有序序列,这也可以作为一种排序方法。

完整代码(没有实现遍历并删除所有节点,道理都一样,懒得写了,你可自己写):

#include <iostream>
#include <list>

using namespace std;

struct BstTreeNode{
    int key;
    struct BstTreeNode *left;
    struct BstTreeNode *right;
};

struct BstTreeNode *parent = NULL;
struct BstTreeNode *search_result = NULL;


//BST search 
bool bst_search(struct BstTreeNode *root, int key) {
    if(root == NULL) { 
        return false;
    }
    if(key == root->key) {
        search_result = root;
        return true;
    }

    if(key < root->key) {
        parent = root;
        return bst_search(root->left, key);
    }
    if(key > root->key) {
        parent = root;
        return bst_search(root->right, key);
    }
}

//BST add
bool bst_add(struct BstTreeNode *root, int key) {
    parent = NULL;
    search_result = NULL;
    if(bst_search(root, key)) {
        return false; //already have this node
    }
    else if(parent != NULL){
        struct BstTreeNode *node = new BstTreeNode;
        node->key = key;
        node->left = NULL;
        node->right = NULL;
        if(key < parent->key)
            parent->left = node;
        else
            parent->right = node;
        
        return true;
    }
    return false;
}

//BST Delete
//Use C++ reference to record the root of the tree
//
bool bst_delete(struct BstTreeNode * &root, int key) {
    parent = NULL;
    search_result = NULL;
    if(!bst_search(root, key)) {
        return false; //have nod this node
    }
    if(search_result->left == NULL && search_result->right == NULL) {
        if(parent != NULL) {
            if(search_result == parent->left)
                parent->left = NULL;
            else if(search_result == parent->right)
                parent->right = NULL;
        }
        else {
            root = NULL;
        }
        delete search_result;
    }
    else if(search_result->left != NULL && search_result->right == NULL) {
        if(parent != NULL) {
            if(search_result == parent->left)
                parent->left = search_result->left;
            else if(search_result == parent->right)
                parent->right = search_result->left;
        }
        else {
            root = search_result->left;
        }
        delete search_result;
    }
    else if(search_result->left == NULL && search_result->right != NULL) {
        if(parent != NULL) {
            if(search_result == parent->left)
                parent->left = search_result->right;
            else if(search_result == parent->right)
                parent->right = search_result->right;
        }
        else {
            root = search_result->right;
        }
        delete search_result;
    }
    else {
        struct BstTreeNode *replace = search_result->left;
        struct BstTreeNode *replace_parent= replace;
        while(replace->right) {
            replace_parent = replace;
            replace = replace->right;
        }
        search_result->key = replace->key;
        if(replace == replace_parent->left)
            replace_parent->left = replace->left;
        else if(replace == replace_parent->right)
            replace_parent->right = replace->left;
        delete replace;
    }
    return true;
} 

//BST traverse, width first search
//Use STL list as a list structure for ease, I do not implement a list 
//Of course, you can implement a list yourself
//
void bst_traverse_wfs(struct BstTreeNode *root) {
    list<BstTreeNode *> my_list;
    if(root != NULL) {
        my_list.push_back(root);
    }
    else {
        return;
    }
    while(!my_list.empty()) {
        struct BstTreeNode *tmp = my_list.front();
        if(tmp->left)
            my_list.push_back(tmp->left);
        if(tmp->right)
            my_list.push_back(tmp->right);
        cout<<tmp->key<<" ";
        my_list.pop_front();
    }
    cout<<endl;
} 

//BST traverse, depth first search, inorder
//Inorder recursive implement
void bst_traverse_dfs_inorder(struct BstTreeNode *root) {
    if(root == NULL)
        return;
    bst_traverse_dfs_inorder(root->left);
    cout<<root->key<<" ";
    bst_traverse_dfs_inorder(root->right);
}

int main() {
    /*                  7
     *            3           9
     *         2     5         10
     *        1     4 6       
     *        
     */


    struct BstTreeNode *root = new BstTreeNode;

    root->key = 7;
    root->left = NULL;
    root->right = NULL;

    //construct & print
    bst_add(root,3);
    bst_add(root,9);
    bst_add(root,2);
    bst_add(root,5);
    bst_add(root,10);
    bst_add(root,1);
    bst_add(root,4);
    bst_add(root,6);
    bst_traverse_wfs(root);
    bst_traverse_dfs_inorder(root);
    cout<<endl;
    cout<<"************************"<<endl;

    //delete & print
    bst_delete(root, 7);
    bst_traverse_wfs(root);
    bst_traverse_dfs_inorder(root);
    cout<<endl;
    cout<<"************************"<<endl;

    return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值