zoukankan      html  css  js  c++  java
  • 倍道而行:二分搜索树删除节点

    二分搜索树的节点的删除还是挺有意思的,下面先从特例开始写,然后通过特例再写通例。


    一、删除最小值所在的节点

    根据二分搜素树的性质可知,最小值就是:至到某左节点没有左孩子,它就是最小值

    代码如下:

     // 在以node为根的二叉搜索树中,返回最小键值的节点
        Node* minimum(Node* node){
            if( node->left == NULL )
                return node;
    
            return minimum(node->left);
        } 

     二、删除最大值所在的节点

    根据二分搜素树的性质可知,最小值所在的节点就是至到某左节点没有左、右孩子,它就是最小值

    代码如下:

    // 在以node为根的二叉搜索树中,返回最大键值的节点
        Node* maximum(Node* node){
            if( node->right == NULL )
                return node;
    
            return maximum(node->right);
        }

     三、删除某一个节点

    如图:

    删除58所在的节点,那哪个节点去取代58所在的位置了?

    方案一:

    根据二叉搜索树的性质可知,58的所有右节点都比它大,58所有的左节点都比它小。所以可以用59取代58的位置。

    用比较标准的说法就是:58所在节点的右孩子的左节点来代替58.

     原因:

    • 改节点是58的某个右节点的一支,所以比50大。
    • 改节点肯定比自己之前的父节点下,因为改节点是父节点的左节点。

    下面就是代码实现:

     // 删除掉以node为根的二分搜索树中的最大节点
        // 返回删除节点后新的二分搜索树的根
        Node* removeMax(Node* node){
    
            if( node->right == NULL ){
    
                Node* leftNode = node->left;
                delete node;
                count --;
                return leftNode;
            }
    
            node->right = removeMax(node->right);
            return node;
        }
    
        // 删除掉以node为根的二分搜索树中键值为key的节点
        // 返回删除节点后新的二分搜索树的根
        Node* remove(Node* node, Key key){
    
            if( node == NULL )
                return NULL;
    
            //如果是某一左节点,好处理,直接删除
            if( key < node->key ){
                node->left = remove( node->left , key );
                return node;
            }//如果是某一右节点,好处理,直接删除
            else if( key > node->key ){
                node->right = remove( node->right, key );
                return node;
            }
            else{   // key == node->key 如果是一个根节点,有以下3种情况
    
                if( node->left == NULL ){
                    Node *rightNode = node->right;
                    delete node;
                    count --;
                    return rightNode;
                }
    
                if( node->right == NULL ){
                    Node *leftNode = node->left;
                    delete node;
                    count--;
                    return leftNode;
                }
    
                // node->left != NULL && node->right != NULL
                Node *successor = new Node(minimum(node->right));
                count ++;
    
                successor->right = removeMin(node->right);
                successor->left = node->left;
    
                delete node;
                count --;
    
                return successor;
            }
        }

     方案二:

    选取,58所在左节点的右节点,即图中的53.也是满足二叉搜索树的性质的。

    代码实现:

     
        // 删除掉以node为根的二分搜索树中键值为key的节点
        // 返回删除节点后新的二分搜索树的根
        Node* removeSomeone(Node* node, Key key){
            
            if (node == NULL) {
                return NULL;
            }
            if (key < node->key) {
                node->left = removeSomeone(node->left,key);
                return node;
            }
            if (key > node->key) {
                node->right = removeSomeone(node->right,key);
                return node;
            }
            
            else{   // key == node->key 如果是一个根节点,有以下3种情况
                //左节点为空 直接把右节点移上去
                if (node->left == NULL) {
                    Node *rightNode = node->right;
                    delete node;
                    count --;
                    return rightNode;
                }
                
                if (node->right == NULL) {
                    Node *leftNode = node->left;
                    delete node;
                    count --;
                    return leftNode;
                }
                
                 // node->left != NULL && node->right != NULL
                //左节点的右子节点
                Node *successor = new Node(maximum(node->left));
                count ++;
                successor->left = removeMax(node->left);
                successor->right = node->right;
                
                delete node;
                count --;
                
                return successor;
                
            }
        } 

    代码中的注释还是蛮详细的,也方便自己以后看。方案二是仿造方案一写的,思想最重要,有了思想,代码表达是迟早的事情。

    但行好事,莫问前程。
  • 相关阅读:
    xposed的基本使用
    scrapy发送邮件
    Image Pipeline
    javax.validation.ConstraintViolationException---Hibernate后台实体校验
    oracle中lead和lag函数 (转载)
    oracle中根据当前记录查询前一条和后一条记录
    物化视图知识了解(转载)
    10个线程同步处理1000行消息
    SQL语句执行效率及分析(note)
    js对文本框特殊字符串过滤
  • 原文地址:https://www.cnblogs.com/yuhui-snail/p/8601796.html
Copyright © 2011-2022 走看看