Linguagem C - Árvores Binárias

Neste artigo, falarei sobre o que é e como implementar uma estrutura de dados chamada Árvore Binária. Com tempos de pesquisa, inserção e remoção expressivamente melhores que de listas encadeadas, esta estrutura é usada principalmente em bancos de dados e sistemas de arquivos.

[ Hits: 50.395 ]

Por: Enzo de Brito Ferber em 07/05/2015 | Blog: http://www.maximasonorizacao.com.br


Conclusão



As árvores binárias são excelentes! Muito eficientes e bastante simples de implementar. O problema de árvores binárias comuns, é que elas se degeneram e nem sempre se degeneram em listas encadeadas, mas em algo entre a árvore ideal e uma lista encadeada - normalmente um tempo médio pior que lg(n) e melhor que (n/2).

Teoricamente, depois de "n" inserções e remoções aleatórias em uma árvore binária comum, espera-se que o tempo médio de pesquisa, remoção e inserção sejam de O(sqrt(n)). Apesar de não crescer tão rápido quanto n/2, sqrt(n) cresce mais rápido que lg(n), então a teórica super-eficiência das árvores é perdida.

Como citado na introdução, o que podemos fazer para tentar preservar essa eficiência é balancear a árvore a cada inserção e remoção, mantendo os tempos de inserção e remoção em [lg(n) + k] (onde 'k' é uma constante determinada pelo número de operações necessárias para balancear a árvore) e mantendo o tempo de pesquisa médio sempre em lg(n).
Linux: Linguagem C - Árvores Binárias
Fonte:
Todas as imagens do artigo foram feitas por mim, exceto esta última sobre a comparação das performances. Todo o conteúdo (texto e código fonte) foi escrito por mim (do código, exceto a função de imprimir a árvore lateralmente. Essa foi idéia do Herbert Schildt, autor de C Completo e Total).

Por motivos didáticos, criei um pequeno programa interativo para demonstrar como as árvores binárias vão crescendo. O código-fonte na próxima seção é um aplicativo interativo que recebe os seguintes comandos simples:
  • i 20 :: vai inserir o elemento 20 na árvore;
  • d 20 :: vai remover o elemento 20 da árvore;
  • m :: vai mostrar a árvore na tela;
  • o :: transversalização ordenada;
  • r :: transversalização pré-ordenada;
  • p :: transversalização pós-ordenada;
  • s :: sai do programa.

Exemplo de output:

    |    Arvores Binarias
    |    Implementacao em C para o Viva O Linux
    |
    |    Autor: Enzo Ferber
    |    2015
    |

                Lista de comandos
                -----------------
                i %d - Inserir um elemento
                d %d - Deletar um elemento
                m    - Mostrar a arvore lateralmente
                o    - Transversalizacao Ordenada
                r    - Transversalizacao Pre-Ordenada
                p    - Transversalizacao Pos-Ordenada
                s    - Sair do programa
                h    - Mostra a ajuda

ArvoreBinaria> i 10 20 30 5 15 25 2 8 12 17
ArvoreBinaria> m
    30
      25
  20
      17
    15
      12
10
    8
  5
    2
ArvoreBinaria> o
2 5 8 10 12 15 17 20 25 30
ArvoreBinaria> d 5 2 8
ArvoreBinaria> m
    30
      25
  20
      17
    15
      12
10
ArvoreBinaria> p
12 17 15 25 30 20 10
ArvoreBinaria> r
10 20 15 12 17 30 25
ArvoreBinaria> d 10 20 15 12 17 25 30
ArvoreBinaria> m
ArvoreBinaria> i 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
ArvoreBinaria> m
                                    19
                                  18
                                17
                              16
                            15
                          14
                        13
                      12
                    11
                  10
                9
              8
            7
          6
        5
      4
    3
  2
1
ArvoreBinaria>>

Observações finais

1. Vale ressaltar que o algoritmo usado para imprimir a árvore lateralmente é muito interessante e vale a pena ser lido.

2. Deixei intencionalmente a função para destruir uma árvore como exercício. Como você implementaria uma função para destruir a árvore? É possível escrever essa função de forma recursiva ou apenas iterativa?

3. Observe a degeneração no último output do exemplo! É uma lista encadeada!

4. Pense um pouco: é possível implementar árvores binárias de forma iterativa? É mais simples ou complexo?

5. Download dos fontes: CodigosFonte_Completo.zip

Bons estudos!

Página anterior     Próxima página

Páginas do artigo
   1. Introdução
   2. Recursividade
   3. Inserção
   4. Pesquisa
   5. Remoção
   6. Transversalização
   7. Conclusão
   8. Código Completo e Comentado
Outros artigos deste autor

Linguagem C - Funções Variádicas

Linguagem C - Listas Duplamente Encadeadas

Leitura recomendada

Linguagem C - Listas Duplamente Encadeadas

Guia de Programação em C/GTK 2 - Construindo uma Calculadora Completa

Otimização de algoritmos

Tutorial SDL

Análise dos Métodos de Ordenação usados em Algoritmos Computacionais

  
Comentários
[1] Comentário enviado por fabio em 07/05/2015 - 12:10h

Parabéns pelo trabalho, dissertação completa sobre o assunto.

[2] Comentário enviado por SamL em 09/05/2015 - 12:49h

Completissimo, muito bom, parabéns.

[3] Comentário enviado por EnzoFerber em 09/05/2015 - 13:34h


Muito obrigado, pessoal.

[4] Comentário enviado por pmargreff em 09/05/2015 - 21:09h


Primeiramente, parabéns pelo artigo.
Segundo, gostaria de saber que programa utilizou para fazer as imagens. Abraço.

[5] Comentário enviado por EnzoFerber em 11/05/2015 - 08:44h


[4] Comentário enviado por pablomrg em 09/05/2015 - 21:09h


Primeiramente, parabéns pelo artigo.
Segundo, gostaria de saber que programa utilizou para fazer as imagens. Abraço.


Bom dia.

Para as imagens usei o primo rico do GIMP! Filho da Adobe!

[]'s

[6] Comentário enviado por dianaluz92 em 12/05/2015 - 15:08h


Parabéns pelo trabalho, a parte conceitual está muito clara da para a estrutura da arvore, mas eu queria tirar um duvida se for possível, como inserir um conjunto de elementos na árvore no caso quando o campo info é um ponteiro que deverá receber elemento tipo inteiro,float e um ponteiro char para nome.
Desde já grata,

[7] Comentário enviado por EnzoFerber em 12/05/2015 - 16:19h


[6] Comentário enviado por dianaluz92 em 12/05/2015 - 15:08h


Parabéns pelo trabalho, a parte conceitual está muito clara da para a estrutura da arvore, mas eu queria tirar um duvida se for possível, como inserir um conjunto de elementos na árvore no caso quando o campo info é um ponteiro que deverá receber elemento tipo inteiro,float e um ponteiro char para nome.
Desde já grata,

Boa tarde.
Pelo que entendi, você quer usar árvores para armazenar uma estrutura sua, certo?

typedef struct data {
int i;
float f;
char *nome;
} data_t;

Coloque os ponteiros direita e esquerda na estrutura que está usando.

typedef struct data* data_t;
struct data {
int i;
float f;
char *nome;
data_t esquerda, direita;
};

Agora é só modificar as funções inserir(), deletar(), procurar(), imprimir(), etc.

if (!raiz) {
...
} else if (strcmp(raiz->nome, nome_ptr) > 0) raiz->direita = inserir(raiz->direita, nome_ptr);
else if (strcmp(raiz->nome, nome_ptr) < 0 ) raiz->equerda = inserir(raiz->esquerda, nome_ptr);
else {
// strcmp() == 0
// dado existente
printf("dado existente!");
return raiz;
}
return raiz;

Espero ter ajudado,
[]'s
Enzo Ferber

[8] Comentário enviado por Ragen em 13/05/2015 - 08:41h

Bom dia Enzo,

Parabéns pelo texto. Vejo que hoje muitos do meio acadêmico não tem nem de longe a sua didática - até porque para ser didático, um professor precisa ser profundo conhecedor do tema.

Eu fiz faculdade em 2003 na PUC-Goiás e me recordo das aulas de ICC2 onde fizemos este caso de B-tree. Logo depois a grade mudou, e o curso afundou em total decadência.

Hoje vejo que muitos alunos se formam bacharéis sem ao menos entender o conceito das árvores binárias. Sem entender o que é um ponteiro, endereço de memória - afinal as faculdades estão pondo Java no lugar do C. Moral da história? Os alunos se formam e não sabem programar - então terminam seus cursos e ficam desempregados e não entendem porque nenhum empresa os querem contratar.

Obrigado por compartilhar conosco este material e seu conhecimento!

[9] Comentário enviado por EnzoFerber em 13/05/2015 - 09:04h


[8] Comentário enviado por Ragen em 13/05/2015 - 08:41h

Bom dia Enzo,

Parabéns pelo texto. Vejo que hoje muitos do meio acadêmico não tem nem de longe a sua didática - até porque para ser didático, um professor precisa ser profundo conhecedor do tema.

Eu fiz faculdade em 2003 na PUC-Goiás e me recordo das aulas de ICC2 onde fizemos este caso de B-tree. Logo depois a grade mudou, e o curso afundou em total decadência.

Hoje vejo que muitos alunos se formam bacharéis sem ao menos entender o conceito das árvores binárias. Sem entender o que é um ponteiro, endereço de memória - afinal as faculdades estão pondo Java no lugar do C. Moral da história? Os alunos se formam e não sabem programar - então terminam seus cursos e ficam desempregados e não entendem porque nenhum empresa os querem contratar.

Obrigado por compartilhar conosco este material e seu conhecimento!


Bom dia, Ragen.
Em primeiro lugar, muito obrigado pelos elogios.

Segundo, concordo plenamente com você (Muita gente e eu, na verdade). Uma dessas pessoas é o CEO do StackExchange, que possui um blog muito bom. O nome dele é Joel Spolsky e o blog é o http://www.joelonsoftware.com. Ele escreveu um artigo precisamente sobre a troca de linguagens "mais baixas" pelo Java nas faculdades, e como isto está arruinando o mercado de trabalho e a qualidade dos profissionais. O artigo chama-se "The Perils of JavaSchool". Excelente texto, vale a pena ser lido. (O blog todo, na verdade)
http://www.joelonsoftware.com/articles/ThePerilsofJavaSchools.html

Pessoalmente, acredito que todos deveriam ter um semestre em Assembly para entender como a CPU/Memória/HD funcionam e interagem - como tudo realmente acontece "embaixo do capô". Faz uma falta danada!

Sobre Joel: http://www.joelonsoftware.com/AboutMe.html
StackExchange: http://www.stackexchange.com

*

http://blog.codinghorror.com/why-cant-programmers-program/
Artigo muito bom também, falando sobre bacharéis que não conseguem programar programas *simples*! Leitura recomendada!


[]'s
Enzo Ferber

[10] Comentário enviado por Ragen em 13/05/2015 - 18:22h


[9] Comentário enviado por EnzoFerber em 13/05/2015 - 09:04h


[8] Comentário enviado por Ragen em 13/05/2015 - 08:41h

Bom dia Enzo,

Parabéns pelo texto. Vejo que hoje muitos do meio acadêmico não tem nem de longe a sua didática - até porque para ser didático, um professor precisa ser profundo conhecedor do tema.

Eu fiz faculdade em 2003 na PUC-Goiás e me recordo das aulas de ICC2 onde fizemos este caso de B-tree. Logo depois a grade mudou, e o curso afundou em total decadência.

Hoje vejo que muitos alunos se formam bacharéis sem ao menos entender o conceito das árvores binárias. Sem entender o que é um ponteiro, endereço de memória - afinal as faculdades estão pondo Java no lugar do C. Moral da história? Os alunos se formam e não sabem programar - então terminam seus cursos e ficam desempregados e não entendem porque nenhum empresa os querem contratar.

Obrigado por compartilhar conosco este material e seu conhecimento!

Bom dia, Ragen.
Em primeiro lugar, muito obrigado pelos elogios.

Segundo, concordo plenamente com você (Muita gente e eu, na verdade). Uma dessas pessoas é o CEO do StackExchange, que possui um blog muito bom. O nome dele é Joel Spolsky e o blog é o http://www.joelonsoftware.com. Ele escreveu um artigo precisamente sobre a troca de linguagens "mais baixas" pelo Java nas faculdades, e como isto está arruinando o mercado de trabalho e a qualidade dos profissionais. O artigo chama-se "The Perils of JavaSchool". Excelente texto, vale a pena ser lido. (O blog todo, na verdade)
http://www.joelonsoftware.com/articles/ThePerilsofJavaSchools.html

Pessoalmente, acredito que todos deveriam ter um semestre em Assembly para entender como a CPU/Memória/HD funcionam e interagem - como tudo realmente acontece "embaixo do capô". Faz uma falta danada!

Sobre Joel: http://www.joelonsoftware.com/AboutMe.html
StackExchange: http://www.stackexchange.com

*

http://blog.codinghorror.com/why-cant-programmers-program/
Artigo muito bom também, falando sobre bacharéis que não conseguem programar programas *simples*! Leitura recomendada!


[]'s
Enzo Ferber


Opa Enzo,

Valeu pela dica. Eu já conhecia o StackExchange, mas não conhecia o blog do fundador - estou lendo os links que recomendou, realmente ótima leitura!

Se tiver Linkedin, me adiciona lá: https://www.linkedin.com/profile/view?id=80923831

[11] Comentário enviado por EnzoFerber em 18/07/2015 - 12:15h

Pessoal,

Na página 4 há um erro. Na função pesquisa esqueci de fazer justamente a comparação que identifica o elemento procurado.
Para utilizar a função corretamente, favor fazer a seguinte modificação:

Após a linha "if (!raiz) return NULL;"
Colocar:
else if (raiz->info == info) return raiz;

É isso.

[]'s


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts