Dando continuidade ao nosso Curso de Programação com a linguagem C, vamos aprender nesta aula como inserir em uma estrutura do tipo árvore binária de forma um pouco mais eficiente, sem retornar nenhum valor e de forma iterativa, ou seja, sem chamadas recursivas.
Quando estamos tentando resolver um problema com programação, nossa primeira preocupação é obviamente resolver o problema, e nesta etapa é normal não pensarmos muito em custos, seja de tempo ou memória. Contudo, o processo de codificação não deveria finalizar ao encontramos a primeira solução.
Ok. Temos uma solução! Será que é possível melhorar?
Se fazer esta pergunta e, claro, buscar respondê-la pode ser um grande aliado no aprendizado da programação.
Nós já vimos duas formas diferentes para inserir em uma árvore binária. Será que é possível realizar esta inserção de forma mais eficiente?
Bom. Se levarmos em conta o custo de acesso à pilha em um processo recursivo, uma versão iterativa pode ser mais rápida e vamos apresentar uma versão nesta aula.
Como não teremos recursão, a primeira ação aqui é encontrar o ponto de inserção. Para isso precisamos percorrer a árvore binária com um loop (um laço, uma repetição). A variável auxiliar aux é inicializada com o ponteiro para a raiz da árvore. Assim, enquanto aux for diferente de null, iremos caminhar na árvore para a direita ou para a esquerda.
Quando a repetição finalizar, significa que encontramos a posição onde será feita a inserção. Perceba que estamos trabalhando aqui com ponteiro para ponteiro para eliminar a necessidade de retorno também. Assim, aux é um filho à esquerda ou à direita de um nó da árvore e seu valor é null. Então, faremos a locação de memória para este filho e salvaremos o valor a ser inserido nesta região de memória.
Perceba que seu filhos são setados para null. A próxima inserção pode ocorrer em um destes filhos, esquerda ou direita.
/*
Procedimento iterativo (sem recursão) para inserir em uma árvore binária
*/
void inserir_versao_3(NoArv **raiz, int num){
NoArv *aux = *raiz;
while(aux){
if(num < aux->valor)
raiz = &aux->esquerda;
else
raiz = &aux->direita;
aux = *raiz;
}
aux = malloc(sizeof(NoArv));
aux->valor = num;
aux->esquerda = NULL;
aux->direita = NULL;
*raiz = aux;
}
Código de exemplo completo de uma Árvore Binária de Busca
/*
Aula 268: Como inserir em uma Árvore Binária de Busca?
TERCEIRA VERSÃO
Código escrito por Wagner Gaspar
Setembro de 2021
*/
typedef struct no{
int valor;
struct no *direita, *esquerda;
}NoArv;
NoArv* inserir_versao_1(NoArv *raiz, int num){
if(raiz == NULL){
NoArv *aux = malloc(sizeof(NoArv));
aux->valor = num;
aux->esquerda = NULL;
aux->direita = NULL;
return aux;
}
else{
if(num < raiz->valor)
raiz->esquerda = inserir_versao_1(raiz->esquerda, num);
else
raiz->direita = inserir_versao_1(raiz->direita, num);
return raiz;
}
}
void inserir_versao_2(NoArv **raiz, int num){
if(*raiz == NULL){
*raiz = malloc(sizeof(NoArv));
(*raiz)->valor = num;
(*raiz)->esquerda = NULL;
(*raiz)->direita = NULL;
}
else{
if(num < (*raiz)->valor)
inserir_versao_2(&((*raiz)->esquerda), num);
else
inserir_versao_2(&((*raiz)->direita), num);
}
}
void inserir_versao_3(NoArv **raiz, int num){
NoArv *aux = *raiz;
while(aux){
if(num < aux->valor)
raiz = &aux->esquerda;
else
raiz = &aux->direita;
aux = *raiz;
}
aux = malloc(sizeof(NoArv));
aux->valor = num;
aux->esquerda = NULL;
aux->direita = NULL;
*raiz = aux;
}
void imprimir_versao_1(NoArv *raiz){
if(raiz){
printf("%d ", raiz->valor);
imprimir_versao_1(raiz->esquerda);
imprimir_versao_1(raiz->direita);
}
}
void imprimir_versao_2(NoArv *raiz){
if(raiz){
imprimir_versao_2(raiz->esquerda);
printf("%d ", raiz->valor);
imprimir_versao_2(raiz->direita);
}
}
int main(){
NoArv *raiz = NULL;
int opcao, valor;
do{
printf("\n\t0 - Sair\n\t1 - Inserir\n\t2 - Imprimir\n");
scanf("%d", &opcao);
switch(opcao){
case 1:
printf("\n\tDigite um valor: ");
scanf("%d", &valor);
//raiz = inserir_versao_1(raiz, valor);
//inserir_versao_2(&raiz, valor);
inserir_versao_3(&raiz, valor);
break;
case 2:
printf("\n\tPrimeira impressao:\n\t");
imprimir_versao_1(raiz);
printf("\n");
printf("\n\tSegunda impressao:\n\t");
imprimir_versao_2(raiz);
printf("\n");
break;
default:
if(opcao != 0)
printf("\n\tOpcao invalida!!!\n");
}
}while(opcao != 0);
return 0;
}
