二叉搜索树删除元素

概念

二叉搜索树(Binary Search Tree)也称作是二叉排序树,它满足以下性质(如果不为空树):

  • 左子树非空则左子树上的所有值均小于根节点的值
  • 右子树非空则右子树上的所有值均大于根节点的值
  • 它的左右子树也分别是二叉搜索树

了解了这些特点。下面来着重说一下BST如何删除元素:

经过观察这些子树地位置关系,我们可以将所有地删除情况分为这几种:

  • 删除的节点是叶子节点
  • 删除的节点只有左子树(右子树)
  • 删除的节点既有左子树也有右子树

分析 & 代码

用代码理解容易一些:

#include<stdio.h>
#include<stdlib.h>
#include<iostream>
using namespace std;
struct node{
    int data;
    struct node * left;
    struct node * right;
};
typedef node * tree;

int ins(tree &t, int key){          //这是建立BST
    if(t==NULL){
        t = new node;
        t->data = key;
        t->left = NULL;
        t->right = NULL;
    }
    else{
        if(t->data > key)
            ins(t->left, key);
        if(t->data < key)
            ins(t->right, key);
    }
}

void inorder(tree t){               //中序遍历
    if(t){
        inorder(t->left);
        cout<<t->data<<" ";
        inorder(t->right);
    }
}

int del(tree &t, int key){
    if(!t)
        return 0;
    else{
        if(t->data == key){
            if(t->left==NULL){                //  这是左子树为空 如果是叶子节点也会在这里处理
                tree temp = t;
                t = temp->right;
                free(temp);
            }
            else if(t->right==NULL){          //  右子树为空的情况
                tree temp = t;
                t = temp->left;
                free(temp);
            }                                       // 左右子树都存在的情况稍微麻烦一些  对于删除这样的节点为了保持BST的性质
            else{                                   //  我们要找到这个节点右侧的最小节点 或者 左侧的最大节点  这里用的是左侧最小节点
                tree temp = t->right;              // 要删除的节点的右侧节点
                while(temp->left){                //   一直找到最小的节点(根据BST的性质 最小节点一定会在最左侧的位置上)
                    temp = temp->left;
                }
                t->data = temp->data;              //覆盖之前节点的值
                del(t->right, temp->data);          //还要删除掉最小的那个节点  这个节点一定是在前面的情况(是叶子节点或者只有右子树)中 所以直接递归调用
            } 
        }
        else if(t->data > key){
            del(t->left, key);
        }
        else if(t->data < key){
            del(t->right, key);
        }
    }
}
int main(){
    tree t= NULL;
    int n;
    int temp;
    cin>>n;
    while(n--){
        cin>>temp;
        ins(t, temp);
    }
    inorder(t);
    cout<<endl;
    for(int i=0; i<5; i++){
        cin>>temp;
        del(t, temp);
        inorder(t);
        cout<<endl;
    }
}

这是我自己的代码,有点乱,所以MOOC上浙江大学的数据结构课对BST的删除元素也做了介绍,这是根据课上的代码改动的代码:

tree findmin(tree t){               // 从当前节点出发找到最小的值
    while(t->left){
        t = t->left;
    }
    return t;
}

int deletetree(tree &t, int key){
    if(!t)
        return 0;
    else if(key < t->data)
        deletetree(t->left, key);           //依然是找到删除节点
    else if(key > t->data)
        deletetree(t->right, key);
    else{
        if(t->left && t->right){                //有做右子树的情况
            tree temp = findmin(t->right);
            t->data = temp->data;
            deletetree(t->right, temp->data);
        }
        else{                              //  只有左子树(右子树)或者没有子树的情况
            tree temp = t;
            if(!temp->left)
                t = t->right;
            else if(!temp->right)
                t = t->left;
            free(temp);
        }
    }
}

整理的还是很简洁的,记录一下。

以上~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值