Você está na página 1de 9

UNIDADE FEDERAL DE SÃO CARLOS

Centro de Ciências Exatas e Tecnologia

Departamento de Computação

Algoritmos e Estruturas de Dados 1

F9 – Árvore Binária de Busca e mais 2 Operações

Professor: Roberto Ferrari Junior

Autor

Pietro Minghini Moralles

792238

Ciência da Computação

São Carlos, 23 de março de 2022


1. Introdução

Nesta atividade, foi proposta uma Árvore Binária de Busca. Esta estrutura é do tipo
árvore binária baseada em nós, em que todos os nós da subárvore esquerda possuem valor
numérico menor ao nó raiz e todos os nós da subárvore direita possuem valor numérico
maior ao nó raiz. A utilização desta estrutura é interessante pois proporciona agilidade
em consultas, sendo estas grande ou pequenas. As condições para ser considerada uma
ABB são:

A ABB possui como operações primitivas a de Cria(), responsável por criar a árvore,
destrói(), responsável por destruir a árvore, vazia(), responsável por verificar se a árvore
esta vazia, estaNaArvore(), responsável por verificar se determinado elemento esta na
árvore, insere(), responsável por inserir um elemento caso este elemento ainda não esteja
na árvore e remove(), que é responsável por remover um elemento caso este se encontre
na árvore.

Um exemplo de uma Árvore Binária de Busca pode ser encontrada na imagem abaixo:
2. Descrição da execução das atividades

Opitei por adcionar duas operações: imprimeTodos(), responsável por imprimir os


elementos da arvore em ordem crescente e nmrNosUmFilho(), responsável por contar a
quantidade de nós que possuem apenas um filho. A definição do TAD pode ser encontrada
abaixo no trecho de código “ABB.h”:

#ifndef ABB_H
#define ABB_H
#include <stdbool.h>

struct Node{
int info;
struct Node *dir;
struct Node *esq;
};

typedef struct Node ArvoreBinaria;

ArvoreBinaria *cria();

bool vazia(ArvoreBinaria *R);

void destroi(ArvoreBinaria *R);

bool estaNaArvore(ArvoreBinaria *R, int X);

ArvoreBinaria *insere(ArvoreBinaria *R, int X, bool *ok);

ArvoreBinaria *Remove(ArvoreBinaria *R, int X, bool *ok);

#endif //ABB_H

Agora, segue abaixo o trecho de código ferente a implementação das funções


primitivas da ABB, encontradas no arquivo “ABB.c”:

#include "ABB.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

ArvoreBinaria *cria(){//Inicia a arvore como NULL


return NULL;
}

void destroi(ArvoreBinaria *R){//Desaloca os elemntos de R


if(R != NULL){
destroi(R->esq);
destroi(R->dir);
free(R);
}
}
bool vazia(ArvoreBinaria *R){//Verifica se a arvore esta vazia
if(R == NULL){
return true;
}
else{
return false;
}
}

bool estaNaArvore(ArvoreBinaria *R, int X){//Percorre os elemntos


da arvore em busca do elemento em questão.
if(R != NULL){
if(R->info == X){
return true;
}
else{
if(R->info > X){
return estaNaArvore(R->esq, X);
}
else{
return estaNaArvore(R->dir, X);
}
}
}
return false;
}

ArvoreBinaria *insere(ArvoreBinaria *R, int X, bool *ok){


if(estaNaArvore(R, X)){//Caso elemento ja esteja na arvore, não
inserimos
*ok = false;
return R;
}
else{
if(R == NULL){//Inserindo um novo elemento na arvore sem
filhos.
ArvoreBinaria *P = (ArvoreBinaria*)
malloc(sizeof(ArvoreBinaria));
P->info = X;
P->dir = NULL;
P->esq = NULL;
*ok = true;
return P;
}
else{
if(R->info > X){
R->esq = insere(R->esq, X, ok);
}
else{
R->dir = insere(R->dir, X, ok);
}
}
}

return R;
}
ArvoreBinaria *Remove(ArvoreBinaria *R, int X, bool *ok) {
if (!estaNaArvore(R, X)) {
*ok = false;
return R;
} else {
if (R != NULL) {
if (X > R->info) {
R->dir = Remove(R->dir, X, ok);
} else if (X < R->info) {
R->esq = Remove(R->esq, X, ok);
} else {
if (R->esq == NULL && R->dir == NULL) {//No sem
filhos
free(R);
*ok = true;
return NULL;
} else if (R->esq == NULL && R->dir != NULL) {//No
com um filho na direita
ArvoreBinaria *aux = R->dir;
free(R);
*ok = true;
return aux;
} else if (R->esq != NULL && R->dir == NULL) {//No
com um filho na esqueda
ArvoreBinaria *aux = R->esq;
free(R);
*ok = true;
return aux;
} else {//No com dois filhos.
ArvoreBinaria *aux = R->dir;
while (aux->esq != NULL) {
aux = aux->esq;
}
int auxRemove = aux->info;
R = Remove(R, auxRemove, ok);
R->info = auxRemove;
*ok = true;
}
}
return R;
}
}
return NULL;
}

Por fim, segue o trecho de código “main.c”, que contem a implementação das duas
funções extras e os testes do TAD:

#include <stdio.h>
#include "ABB.h"

void imprimeTodos(ArvoreBinaria *R);

void nmrNosUmFilho(ArvoreBinaria *R, int *X);

int main() {
bool ok;
ArvoreBinaria *ABB1 = cria();
int X, op = 10;

while(op != 0){
printf("-- MENU -- (1) VAZIA -- (2) DESTROI -- (3) INSERE -
- (4) REMOVE -- (5) IMPRIME -- (6) FILHOS UNICOS\n");
scanf("%d", &op);

if(op == 1){
if(vazia(ABB1)){
printf("Arvore vazia.\n");
}
else{
printf("Arovre n vazia.\n");
}
}
else if(op == 2){
if(vazia(ABB1)){
printf("Arvore vazia.\n");
}
else{
destroi(ABB1);
printf("Arvore destruida.\n");
}
}
else if(op == 3){
printf("Digite o valor de X a ser inserido: ");
scanf("%d", &X);
ABB1 = insere(ABB1, X, &ok);
if(ok){
printf("Elemento %d inserido.\n", X);
}
else{
printf("Elemento %d n inserido pois ja esta na
arvore.\n", X);
}
}
else if(op == 4){
printf("Digite o valor de X a ser removido: ");
scanf("%d", &X);
ABB1 = Remove(ABB1, X, &ok);
if(ok){
printf("Elemento %d removido.\n", X);
}
else{
printf("Elemento %d nao esta na arvore.\n", X);
}
}
else if(op == 5){
imprimeTodos(ABB1);
printf("\n");
}
else if(op == 6){
int qtdNosUnicos = 0;
nmrNosUmFilho(ABB1, &qtdNosUnicos);

printf("Nos com um unico filho: %d\n", qtdNosUnicos);


}
}

return 0;
}

void imprimeTodos(ArvoreBinaria *R){//Função que imprime os


elementos da arvore em ordem crescente.
if(R != NULL){
imprimeTodos(R->esq);
printf("%d " , R->info);
imprimeTodos(R->dir);
}
}

void nmrNosUmFilho(ArvoreBinaria *R, int *X){


if(R != NULL){
nmrNosUmFilho(R->esq, X);
nmrNosUmFilho(R->dir, X);
if(R->dir != NULL && R->esq == NULL){
*X = *X + 1;
}
else if(R->dir == NULL && R->esq != NULL){
*X = *X + 1;
}
}
}
3. Prints de Execução

Seguem agora prints que comprovem a funcionalidade do algoritmo:

Você também pode gostar