Explicação detalhada da operação de exclusão da árvore de pesquisa binária, com imagens e textos para simplificar o complexo


Prefácio


1. Conceito de árvore de pesquisa de árvore binária

Uma árvore de pesquisa binária também é chamada de árvore de classificação binária e possui as seguintes propriedades de uma árvore binária:
-Se sua subárvore esquerda não estiver vazia, o valor de todos os nós na subárvore esquerda é menor que o valor do nó raiz;
-se Sua subárvore direita não estiver vazia, então os valores de todos os nós na subárvore direita são maiores que o valor do nó raiz; -Suas
subárvores esquerda e direita também são árvores binárias de pesquisa, respectivamente.

A ordem do meio da árvore de pesquisa da árvore binária deve estar em ordem.
int [] a = {5,3,7,1,4,6,8,9}; Travessia
em ordem: {1,3,4,5,6,7,8,9};

Insira a descrição da imagem aqui

O percurso e a inserção da árvore binária de pesquisa são relativamente simples, então aqui vou explicar principalmente a operação de exclusão da árvore binária de pesquisa. Assisti várias vezes ao vídeo da operação de exclusão da árvore binária explicada pelo professor e também assisti a vários artigos explicando a operação de exclusão da árvore de pesquisa binária. Sim, finalmente entendi, então quero registrar este processo de aprendizagem à minha própria maneira.

Dois, a explicação da operação de exclusão da árvore binária

1. Discussão por situação:

A operação de exclusão pode ser dividida em 3 situações: nó é o nó a ser excluído e pai é o nó pai do nó a ser excluído

1. Os filhos esquerdo e direito do
não existem 2. O nó tem apenas os filhos esquerdos ou apenas os filhos
3. Existem os filhos esquerdo e direito do nó

O primeiro caso : quando os filhos esquerdo e direito do nó do nó a ser excluído não existem, então é um nó folha ou uma árvore com apenas um nó raiz; se o nó for o nó raiz ao excluir, deixe o nó raiz ser Vazio; se o nó for o filho esquerdo de seu nó pai, defina o filho esquerdo do pai como vazio; caso contrário, defina o filho direito do pai como vazio. (Se você não entende este parágrafo, você pode fazer um desenho e tentar por si mesmo, confie em você) O
Insira a descrição da imagem aqui
código é o seguinte:

   if(node.left==null&&node.left==null){
    
    
            if(node==root){
    
    
                root=null;
            }else if(node==parent.left){
    
    
                parent.left=null;
            }else{
    
    
                parent.right=null;
            }
   }

O segundo caso : quando o nó do nó a ser excluído tem apenas o filho esquerdo ou o filho direito, então duas conexões devem ser quebradas ao excluir, nó e pai, nó e seus nós filhos; em seguida, crie uma nova conexão; conforme mostrado no figura abaixo: quando o nó a ser excluído não tem filho esquerdo, é a situação à esquerda na figura abaixo:
1. Primeiro, se o nó a ser excluído é o nó raiz, deixe o filho esquerdo do nó ser excluído seja a raiz;
2. Se o nó a ser excluído como seu pai filho esquerdo, deixe o nó filho esquerdo a ser excluído apontando seu pai.
3. Se o nó a ser excluído for o filho direito de seu nó pai, deixe o filho esquerdo do nó a ser excluído apontar para seu nó pai.

Insira a descrição da imagem aqui

if(node.left!=null&&node.right==null){
    
    
            //有左孩子,没有右孩子
            if(node==root){
    
    
                root=node.left;
            }else if(node==parent.left){
    
    
                parent.left=node.left;
            }else{
    
    
                parent.right=node.left;
            }
            
        }else if(node.left==null&&node.right!=null){
    
    
        //有右孩子,没有左孩子
            if(node==root){
    
    
                root=node.right;
            }else if(node==parent.left){
    
    
                parent.left=node.right;
            }else{
    
    
                parent.right = node.right;
            }
        }

O terceiro caso :
quando o nó a ser excluído tem filhos esquerdo e direito, o método de substituição é usado para definir dois nós, fantasma e ghostParent , e o fantasma armazena o maior nó na subárvore esquerda (ou filho direito) do nó para ser excluído Substitua pelo menor valor na árvore), ghostParent salva o nó pai do fantasma. Depois de encontrar o fantasma, substitua o valor do nó a ser excluído pelo valor do fantasma e, em seguida, julgue se o nó a ser excluído tem um filho esquerdo, em caso afirmativo, deixe-o ficar O filho aponta para seu nó pai (ghostParent).

Insira a descrição da imagem aqui

            Node ghost=node.left;
            Node ghostParent=null;
            while(ghost.right!=null){
    
    
                ghostParent=ghost;
                ghost=ghost.right;
            }
            //进行替换
            node.key=ghost.key;
            //删除ghost结点(其右孩子一定为空)
            if(node==ghostParent){
    
    
                ghostParent.left=ghost.left;
            }else{
    
    
                ghostParent.right=ghost.left;
            }

2. Código completo

public boolean remove(Integer key){
    
    
        //找要删除的结点key所在的结点为node,node的双亲结点,记作parent
        Node current=root;
        Node parent=null;
        while(current!=null){
    
    
            int comp=key.compareTo(current.key);
            if(comp==0){
    
    
                removeInternal(current,parent);
                return true;
            }else if(comp<0){
    
    
                parent=current;
                current=current.left;
            }else{
    
    
                parent=current;
                current=current.right;
            }
        }
        return false;
    }
    private void removeInternal(Node node,Node parent){
    
    
        //总共有四种情况:1.两边都没有左右孩子 2.只有一边有孩子  3.两边都有子孩子

        //node为要删除的结点
        if(node.left==null&&node.left==null){
    
    
            if(node==root){
    
    
                root=null;
            }else if(node==parent.left){
    
    
                parent.left=null;
            }else{
    
    
                parent.right=null;
            }
        }else if(node.left!=null&&node.right==null){
    
    
            //有左节点,没有右节点

            if(node==root){
    
    
                root=node.left;

            }else if(node==parent.left){
    
    
                parent.left=node.left;
            }else{
    
    
                parent.right=node.left;
            }
        }else if(node.left==null&&node.right!=null){
    
    
            if(node==root){
    
    
                root=node.right;
            }else if(node==parent.left){
    
    
                parent.left=node.right;
            }else{
    
    
                parent.right = node.right;
            }
        }else{
    
    
            //左右孩子都有的时候
            Node ghost=node.left;
            Node ghostParent=null;
            while(ghost.right!=null){
    
    
                ghostParent=ghost;
                ghost=ghost.right;
            }
            //进行替换
            node.key=ghost.key;
            //删除ghost结点(其有孩子一定为空)
            if(node==ghostParent){
    
    
                ghostParent.left=ghost.left;
            }else{
    
    
                ghostParent.right=ghost.left;
            }
        }
    }


Resumindo

1. Para a operação de exclusão, o código não é complicado. Os primeiros dois casos são relativamente simples de considerar, principalmente o terceiro caso, que é um pouco complicado. A ideia de substituição é usada para encontrar o maior valor à esquerda subárvore do nó a ser excluído ou o menor valor na subárvore certa pode ser substituído para garantir que a estrutura da árvore de pesquisa binária esteja completa.
2. Nosso professor disse que escrever código é, na verdade, a última etapa de resolver um problema . Primeiro, você precisa aprender a analisar um problema. É melhor repassar a ideia em sua mente, combinar o desenho e começar depois compreender o processo. É uma forma eficaz de melhorar a capacidade de código de alguém.

Acho que você gosta

Origin blog.csdn.net/m0_46551861/article/details/109324429
Recomendado
Clasificación