Artigo Diretório
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};
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ó 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
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.
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).
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.