删除二叉搜索树节点

168 阅读1分钟

删除二叉搜索树某个节点,分为三种情况,度为0的,度为1的,度为2的。

image.png

image.png

image.png


//根据元素删除节点
- (void)removeElement:(NSInteger)element{
    [self removeNode:[self node:element]];
}

//根据节点删除节点
- (void)removeNode:(Node *)node{
    
    if (node == nil) {
        return;
    }
    
    self.size--;
    
    if ([node hasTwoChildren]) { //有左右节点
        //找到后继节点
        Node *s = [self successorNode:node];
        //用后继节点的值覆盖本身节点
        node.element = s.element;
        //保存该后继节点局部值以便外界删除操作
        node = s;
    }
    
    //开始删除节点,程序能执行到这儿,节点度必然为0或1
    
    //保存节点的子节点(此处如果度为0,那么replacement必然是nil了,所以不用单独获取度为0的子节点)
    Node *replacement = node.left != nil ?  node.left :  node.right;

    if (replacement != nil) { //度为1的节点
        
        //更改子节点的parent
        replacement.parent = node.parent;
        //更改node节点的parent节点的指向
        if (node.parent == nil) { //此处是度为1的节点,且是根节点
            self.root = replacement;
        }else if (node == node.parent.left) {
            node.parent.left = replacement;
        }else if (node == node.parent.right){
            node.parent.right = replacement;
        }
        
    }else { //度为0的节点
        if (node.parent == nil) { //此处是度为0的叶子节点,且是根节点
            
            self.root = nil;
            
        }else {//度为0的节点,但不是根节点
            
            if (node == node.parent.left) { //叶子节点为父节点的左节点
                node.parent.left = nil;
            }else if (node == node.parent.right){ //叶子节点为父节点的右节点
                node.parent.right = nil;
            }
        }
    }

}

//根据元素返回节点
-(Node *)node:(NSInteger)element{
    Node *node = self.root;
    while (node != nil) {
        NSInteger cmp = element - node.element;
        if (cmp == 0 ) {
            return node;
        }else if (cmp > 0){
            node = node.right;
        }else {
            node = node.left;
        }
    }
    return nil;
}