二叉树·二叉搜索树·插入-查询-删除

	二叉搜索树,(二叉排序树,二叉查找树),BST是一种很实用的查找数据结构,虽相较于map,set的红黑树(RB-Tree)而言,并不那么突出,但是也已经平均能在logn的时间复杂度内得到结果。
    BST的插入,查找,找最大/小值,前/中/后序遍历都比较简单,其难点在于其节点的删除。
	我们先简单的介绍一下BST除删除以外的基本操作。
	
**一、构造BST**
typedef struct BSTree {
    int data;         //节点值
    BSTree* left;      // 左孩子
    BSTree* right;     // 右孩子
    BSTree* parent;        //父节点
}*BST;

**二、节点插入**
BSTree* Insert_Tree(BSTree* root, int key) {
    if (root == NULL) {               //若这棵树是空树,那么将此值赋给根节点
        root = (BSTree*)malloc(sizeof(BSTree));
        root -> data = key;
        root -> left = NULL;
        root -> right = NULL;
        return root;
    }
    else if (key < root -> data) {    //非空,若小于根节点,在左子树中寻找
        root -> left = Insert_Tree(root -> left, key);
        return root;
    }
    else if (key > root -> data) {    //非空,若大于根节点,在右子树中寻找
        root -> right = Insert_Tree(root -> right, key);
        return root;
    }
}


**三、节点查询**

bool Search_Tree(BST root, int key) {   //寻找树中某一值
    if (root == NULL) {
        return false;
    }
    else if (key < root -> data) {
        return Search_Tree(root -> left, key);
    }
    else if (key > root -> data) {
        return Search_Tree(root -> right, key);
    }
    else return true;
}

**四、查询子树最大/小值**
BST Find_Min(BST root) {           //找到树中最小值
    if (root == NULL) {
        return NULL;
    }
    else if (root -> left == NULL) {
        return root;
    }
    else {
        return Find_Min(root -> left);
    }
}

BST Find_Max(BST root) {          //找到树中最大值
    if (root == NULL) { 
        return NULL;
    }
    else if (root -> right == NULL) {
        return root;
    }
    else return Find_Max(root -> right);
}

**五、遍历(中序遍历为例)**
void print(BSTree* root) {   //中序遍历打印这棵树
    if (root != NULL) {
        print(root -> left);
        cout << root -> data << endl;
        print(root -> right);
    }
    return ;
}

前面的操作较为简单,接下来我们分析删除操作;
	
	主要分为以下几种情况(参照白书):
·若该节点只有右儿子,那么将右儿子直接代替该节点
	·若该节点的左儿子的右儿子不存在,那么将该节点的左儿子代替该节点
	·若前两种情况都不符合,那么直接将左子树的最大节点提到该节点的位置上来
看过白书之后我产生了某些疑问,可能有的人也有某些疑问吧,
	1、若只有左子树,可不可以将左儿子向第一种情况进行处理?是可以的。
	2、如果我的右儿子的左子树不存在,可不可以像第二种情况进行处理?也是可以的
	3、那么BST(同时有左右儿子)删除节点可不可以一直只在左子树中寻找最大节点并将其提到删除节点位置处呢?
		也是可以的。
	白书上的做法只是将很多的情况进行了分析优化,像网上很多博客里,先细分了有无子树,有无左右子树之类的较为
繁琐,在这里我还是推荐一博客
	神秘而刺激的东西
	他讲解了删除操作,个人觉得相较于其他博客简单易懂。
	下面,我们来写出删除操作

BSTree* Delete_Tree(BST root, int key) {  //删除树
    if (root == NULL) {
        return NULL;
    }
    else if (key < root -> data) {
        root -> left = Delete_Tree(root -> left, key);
    }
    else if (key > root -> data) {
        root -> right = Delete_Tree(root -> right, key);
    }
    else if (root -> left == NULL) {
        BST temp = root -> right;
        delete root;
        return temp;
    }
    else if (root -> left -> right == NULL) {
        BST temp = root -> left;
        temp -> right = root -> right;
        delete root;
        return temp;
    }
    else {
        BST temp;
        for (temp = p -> right; temp -> right -> right != NULL; temp = temp -> right);
        BST ans = temp -> right;
        temp -> right = ans -> left;
        ans -> left = root -> left;
        ans -> right = root -> right;
        delete root;
        return ans;
    }
    return root;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值