Algoritmos e Estrutura de Dados
Básico das Engenharias e Computação
Árvores
Paulo Cesar Lopes Email: [email protected]
www.sites.google.com/site/algoritmosestruturas
Bibliografia
• MANZANO, José Augusto N. G.; OLIVEIRA, Jayr Figueiredo. Algoritmos: lógica para desenvolvimento de programação de computadores. 17.ed. São Paulo: Érica, 2005.
• ASCENCIO, Ana Fernanda Gomes; VENERUCHI, Edilene Aparecida.
Fundamentos de programação de computadores: algoritmos, C/C++ e C/C++. São Paulo: Prentice Hall, 2002.
• FERRARI, Fabricio; CECHINEL, Cristian; Apostila de Introdução a Algoritmos e Estrutura de Dados. Universidade Federal do Pampa. Disponível em
http://www.dcc.ufam.edu.br/david/dmdocuments/Introducao-a-algoritmos.pdf • PARLANTE, Nick; Binary Trees - The article introduces the basic concepts of
binary trees. Disponível em: http://cslibrary.stanford.edu/110/BinaryTrees.html. • Apostila Árvores. http://equipe.nce.ufrj.br/adriano/c/apostila/arvore.htm#defarvores • Aplicação interessante para compreender árvores AVL http://www.csi.uottawa.ca/
~stan/csi2514/applets/avl/BT.html
• Árvore AVL - http://pt.wikipedia.org/wiki/Árvore_AVL
• `http://webpages.ull.es/users/jriera/Docencia/AVL/AVL%20tree%20applet.htm
Algoritmos e Estrutura de Dados
•
Bibliografia
•
Grafos
– Breve Histórico
– Conceitos, Recursos e Utilização – Motivação, Prática, e Representação
•
Árvores
– Conceitos
– Arvores Binárias
• Modelos matemáticos
• Armazenamento
• Funções e Procedimentos Agenda
Breve Histórico
Tudo começou no século XVIII, na cidade medieval de Königsberg, situada no leste
europeu, banhada pelo rio Pregel, que dividia a cidade em quatro áreas de terra ligadas
umas às outras por sete pontes, as famosas “sete pontes de Königsberg”.
Durante muito tempo se discutiu se era possível cruzar as sete pontes numa caminhada contínua, sem que se passasse duas vezes por qualquer uma delas. Leonhard Euler estudou este problema em 1736 e a partir daí
Algoritmos e Estruturas de Dados
Conceitos e Representação Matemática
Matematicamente:
G(V,A) é definido pelo par de conjuntos não vazios V e A, onde:
V - conjunto dos vértices do grafo; A - conjunto de pares ordenados
a= (v,w), v e w V: as arestas do grafo.
Vértices adjacentes: são aqueles que estão ligados por uma mesma aresta.
Aresta incidente: é aquela que liga dois vértices distintos.
Grau de um vértice é igual ao número de arestas nele incidentes.
Grafo Regular é aquele em que todos os vértices têm o mesmo grau.
Grafo Completo é aquele em que todos os vértices são adjacentes.
Um grafo G diz-se um Grafo Bipartido se o conjunto dos seus vértices admitir uma partição {V1, V2 } de tal forma, que toda a aresta de
G une um vértice de V1 e um vértice de V2.
Um grafo planar é um grafo que pode ser desenhado em apenas duas dimensões garantindo que as arestas não se cruzem.
Algoritmos e Estruturas de Dados
Grafos
G=(V(G), E(G),
G), onde
V(G) ={1, 2, 3, 4, 5}
E(G)={e1, e2, e3, e4, e5, e6, e7 , e8}
G :
G(e1)= (1, 2), G(e2)= (1, 4),
5
1
2
3
4
A
C B
A
A
A
B
A
A
C
B
C B
C B
Algoritmos e Estruturas de Dados
• Grafo Não Direcional:
– São grafos onde as arestas E(G) não são ordenadas
(direcionadas), ou seja, a ARESTA (V1, V2) é a
mesma ARESTA (V2, V1)
• Grafo Direcional (Dígrafo):
– São grafos onde as arestas E(G) são ordenadas
(direcionadas), ou seja, a ARESTA (V1, V2) é
diferente da ARESTA (V2, V1)
Grafos
Prática e Motivação
Muitas aplicações em computação necessitam considerar conjunto de conexões entre pares de objetos:
Existe um caminho para ir de um objeto a outro seguindo as conexões? Qual é a menor distância entre um objeto e outro?
Quantos outros objetos podem ser alcançados a partir de um determinado objeto?
Grafos são utilizados para modelar tais problemas.
Exemplo clássico para Engenharias e Computação:
` MÁQUINAS de ESTADOS
Algoritmos e Estruturas de Dados
Representação - Matriz
Grafos
Seja G = (V, A) um grafo com N vértices, a matriz de adjacência “A” de “G” é um arranjo bidimensional NXN, com as seguintes propriedades:
A[i, j] = 1, se existe um arco do vértice i ao vértice j (ou incide em j, no caso de grafos direcionados)
A[i, j] = 0, caso contrário
Em casos de grafos ponderados (com pesos associados às arestas),
o valor a ser inserido refere-se ao peso da aresta;
A B C D
Representação - Matriz
Seja G = (V, A) um grafo com N vértices, a matriz de adjacência “A” de “G” é um arranjo bidimensional NXN, com as seguintes propriedades:
A[i, j] = 1, se existe um arco do vértice i ao vértice j (ou incide em j, no caso de grafos direcionados)
A[i, j] = 0, caso contrário
Em casos de grafos ponderados (com pesos associados às arestas),
o valor a ser inserido refere-se ao peso da aresta;
A B C D
Algoritmos e Estruturas de Dados
Representação – Lista Encadeada
Grafos
Na Lista de Adjacências, as linhas da matriz são representadas por listas encadeadas.
Cada vértice corresponde a uma linha
Vértices que contém ligações diretas têm um nó associado na linha
Um vetor Vi é usado como cabeçalho para estas listas, onde i é um determinado vértice.
A
B
Definição
Seja G um grafo. G é uma árvore se satisfaz as seguintes condições:
1. G é conexo e há exatamente um caminho entre dois vértices quaisquer.Já em uma floresta, há no máximo um caminho entre dois vértices, devido à não-conectividade.
2. G é acíclico, e um simples ciclo é formado se qualquer aresta for adicionada a G.
3. G é conexo, e deixará de ser conexo se qualquer aresta for removida de G.
4. G é conexo, acíclico e tem n − 1 arestas.
Conceitos e Recursos
Algoritmos e Estrutura de Dados
É uma árvore um grafo
Conceitos e Recursos
Nível 2 Nível 1 Nó raiz
A
C
F E
D
Nível 0
Altura da árvore
B
Nós internos
Folhas
B
E
Nó pai
Nó filho
Conceitos e Recursos
Algoritmos e Estrutura de Dados
Uma árvore pode ser classificada de diversas formas diferentes, uma
delas é pelo número máximo de nós-filhos que cada nó-pai pode ter:
– Binária (dois nós);
– Ternária (três nós);
– Quaternária (quatro nós);
– N-ária (N nós);
– Não N-ária (quando não conhecemos ou não há um
número máximo de nós-filhos para cada nó-pai).
Conceitos e Recursos
• Todo nó da árvore possui no máximo 2 nós filhos
Exceto os nós folha, que devem possuir exatamente 0 filhos
• É muito utilizada para tomadas de decisões bidirecionais
em cada ponto ou momento.
Árvores Binárias
A
C
F E
D G
B
Conceitos e Recursos
Algoritmos e Estrutura de Dados
Árvores Binárias
Árvore Binária Completa de nível
n:
•
t
odas as folhas estejam no nível
n
Se contiver
m
nós no nível
l
,
•
ela conterá no máximo 2m nós no nível l+1
Uma árvore binária completa de nível
n
contém:
•
exatamente
2
nnós em cada lível
l
entre
0
e
n
•
profundidade n com exatamente
2
nnós no nível
n
Conceitos e Recursos
Árvores Binárias
É possível calcular o nível k de uma árvore binária completa
se for informado o número total de nós (t
nconhecido)?
1
)
1
(
log
2
t
nImplementação
Algoritmos e Estrutura de Dados
Árvores Binárias
Árvoresraiz
esq A dir
B C
E F
D
Conceitos e Recursos
Árvores Binárias
• Os nós de uma árvore binária quase completa podem ser numerados. • 1 para a raiz e filho esquerdo é o dobro do n. do pai e o filho direito é o
dobro + 1 do n. do pai.
• A numeração ajuda nas implementações.
• Facilita na localização de itens. A
B
D E
I
D
G F
1
2 3
4 5 6 7
Implementação
Algoritmos e Estrutura de Dados
Árvores Binárias
• Possuem um número constante de sub-árvores em
cada nó.
– Limitação do número de ponteiros usados
• Algoritmos conhecidos e eficientes para o tratamento.
• A forma de armazenar os nós surge naturalmente de
sua definição:
– Ponteiro para o nó raiz (como nas listas lineares).
– Ponteiros para os filhos: esq e dir.
Implementação
Árvores Binárias
tipo
Ponteiro = ^TipoNo; TipoItem = registro
chave: TipoChave;
{outra variáveis..} fimregistro;
TipoNo = registro
Reg: TipoItem;
esq, dir: Ponteiro; fimregistro;
TipoArvoreBin = Ponteiro;
typedef struct No { int numero;
Implementação
Algoritmos e Estrutura de Dados
Árvores Binárias
Árvores1. Inicial(Arvore): apenas define um arvore vazia
2. CriarRaiz(Arvore): retorna nó raiz da árvore que foi criada em Arvore
3. Vazia(Arvore): retorna Verdadeiro se a árvore está vazia e Falso do contrário;
4. InsereFilhoaDireita: (Arvore,pai,item): Insere o elemento item na árvore à direita do nó pai se já não possui um filho à direita;
5. InsereFilhoaEsquerda: (Arvore,pai,item): Insere o elemento item na árvore à esquerda do nó pai se já não possui um filho a esquerda;
6. Busca(Arvore, item,pont): retorna o ponteiro pont para o nó item em Arvore; e se item não existe retorna NULL
7. PercursoPosOrdem(Arvore), PercursoPreOrdem(Arvore), PercursoEmOrdem(Arvore): percorre nós em ordem;
Implementação Pré-Ordem – Pre-order
Árvores Binárias
Exemplos de Implementações
tipo
ElementoPonteiro = ^TipoNo; TipoNo = registro
Nome : vetor [1..100] de character esq, dir: ElementoPonteiro;
fimregistro;
Arv, Raiz, Arvore = ElementoPonteiro;
Início /* Definição da Arvore */ struct Elemento // Define cada nó {
char nome [100];
struct Elemento* esq; struct Elemento* dir; };
typedef struct Arvore Arv;
struct Elemento* Raiz; //Ponteiro para o “topo” da Árvore struct Elemento* Arvore; //Ponteiro para a Árvore
` ... ...
Implementação Pré-Ordem – Pre-order
Algoritmos e Estrutura de Dados
Árvores Binárias
ÁrvoresExemplos de Implementações
void insere_ordenado (struct Elemento **nodo, char *nome2) {
struct Elemento *novo_no;
novo_no = (struct Elemento *) malloc(sizeof(struct Elemento) ); strcpy(novo_no->nome, nome2); // Copia nome
if(*nodo == NULL) // A árvore está vazia!!! {
novo_no->esq = NULL; novo_no->dir = NULL; *nodo = novo_no;
}
else // A arvore não está vazia!!! {
Implementação Pré-Ordem – Pre-order
Árvores Binárias
Exemplos de Implementações
// Remove toda a arvore
Arv *remove (struct Elemento *nodo) { if(nodo!= NULL) { remove(nodo->esq); remove(nodo->dir); free(nodo); } return NULL; }
/* Função imprime na tela a árvore */
Implementação Pré-Ordem – Pre-order
Algoritmos e Estrutura de Dados
Árvores Binárias
Árvores1. Se árvore vazia fim 2. visitar o nó
3. percorrer em pré-ordem a sub-árvore esquerda 4. percorrer em pré-ordem a sub-árvore direita
ABDCEGFHI ABDCEGFHI RECU RSIV IDAD E
função x (no) Início
processa no;
aplica função x para filho a esquerda; aplica função x para filho a direita; void pre_ordem (struct Elemento *raiz) {
if (raiz) { visita(raiz);
pre_ordem(raiz->esq); pre_ordem(raiz->dir); }
Implementação Em Ordem - In-order
Árvores Binárias
1. Se árvore vazia fim
2. percorrer em ordem a sub-árvore esquerda 3. visitar o nó
4. percorrer em ordem a sub-árvore direita
função x (no) Início
aplica função x para parte dos filhos do no; processa no;
aplica função x para parte dos filhos do no; Fim;
void em_ordem (struct Elemento *raiz) { if (raiz) {
em_ordem(raiz->esq); visita(raiz);
em_ordem(raiz->dir); }
Implementação Pós-ordem - Pos-order
Algoritmos e Estrutura de Dados
Árvores Binárias
Árvores1. Se árvore vazia fim
2. percorrer em ordem a sub-árvore esquerda 3. percorrer em ordem a sub-árvore direita 4. visitar o nó
DBGEHIFCA
DBGEHIFCA
função x (no) Início
aplica função x para filho a esquerda; aplica função x para filho a direita; void pos_ordem (struct Elemento *raiz) { if (raiz) {
pos_ordem(raiz->esq); pos_ordem(raiz->dir); visita(raiz);
Implementação Inserção em uma Árvore
Árvores Binárias
Cria-se o novo nó (método new) e preenche-se o mesmo com as informações/dados;
Utiliza-se algum critério para determinar qual nó e em qual posição o novo nó deverá ficar na árvore;
Implementação Remoção em uma Árvore
Algoritmos e Estrutura de Dados
Árvores Binárias
ÁrvoresUtiliza-se de um outro ponteiro ( t ) para apontar para o objeto que vai ser removido;
Reorganiza-se os filhos a fim de que seu pai possa apontar para esses e ninguém ficar “abandonado”, eliminando o vínculo entre a árvore e o nó-alvo;
Implementação
Árvores Binárias
procedimento Inicializa(var Arvore: TipoArvoreBin); Inicio
Arvore := NULL; Fimprocedimento;
procedimento CriarRaiz(var Arvore: TipoArvoreBin); var no: TipoArvoreBin;
inicio
novo(nó);
no^.esq := NULL; no^.dir := NULL; Arvore := no; fimprocedimento;
funcao Vazia(var Arvore: TipoArvoreBin): logica; Inicio
Implementação
Algoritmos e Estrutura de Dados
Árvores Binárias
Árvoresprocedimento InserirFilhoaDireita(var Arvore: TipoArvoreBin;
pai: TipoItem; item: TipoItem); var p, no: TipoArvoreBin;
inicio
Busca(Arvore, pai, p);
se (p<>NULL) entao
se (p^.dir <> NULL) entao
escreval("item possui subárvore direita") senao inicio
novo(no);
no^.esq := NULL; no^.dir := NULL;
Implementação
Árvores Binárias
procedimento InserirFilhoaEsquerda(var Arvore: TipoArvoreBin;
pai: TipoItem; item: TipoItem); var p, no: TipoArvoreBin;
final
Busca(Arvore, pai, p);
se (p<>NULL) entao
se (p^.esq <> NULL) entao
escreval("item possui subárvore esquerda") senao inicio
novo(no);
no^.esq := NULL; no^.dir := NULL;
no^.Reg.Chave := item.Chave; p^.esq := no;
Conceitos e Recursos
Algoritmos e Estrutura de Dados
Árvores Binárias de Busca ou Pesquisa
ÁrvoresTambém conhecidas como árvores de busca binária;
São árvores em que é possível determinar em que direção buscar
um dado nó a partir do valor do pai e levando-se em consideração
alguma regra quanto à disposição dos filhos;
Nós com valores menores que o pai à esquerda,
Nós com valores maiores que o pai à direita;
Conceitos e Recursos
Árvores Binárias
Remover um nó que possui dois filhos
– Escolher o nó mais à esquerda da sub-árvore direita (ou mais à direita da sub-árvore esquerda) para “substituí-lo;
Conceitos e Recursos: Árvore Balanceada
Algoritmos e Estrutura de Dados
Árvores AVL
ÁrvoresAVL: Árvore de Busca Binária Auto-Balanceada. Ela mantém
o balanceamento de sua árvore em cada operação de
inclusão ou retirada de um nó.
A maior diferença possível entre os níveis de dois nós-folhas é 1.
Balanceamento Estático
O balanceamento estático de uma árvore binária consiste em construir uma nova versão, reorganizando-a.
Balanceamento Dinâmico: AVL
Árvore AVL em homenagem aos matemáticos russos (Adelson-Velskiie Landism-1962)
Conceitos e Recursos
Árvores AVLs
•Efetuar a busca pelo nó (como qualquer outra árvore de busca).
•Rotacionar até que o mesmo seja um nó-folha e remova-o; a remoção
de um nó sem filhos é o caso mais simples!
•Verificar se árvore se encontra balanceada, caso não esteja, efetue
rotações. Efetua-se a busca pelo nó (como qualquer outra árvore de
busca);
•Rotacionar até que o mesmo seja um nó-folha e remova-o; a remoção
de um nó sem filhos é o caso mais simples!
Conceitos e Recursos
Algoritmos e Estrutura de Dados
Árvores AVL
ÁrvoresInserção
• Busca pelo nó mais próximo (igual a qualquer outra árvore de busca binária); • Insere-se o nó;
• Verifica-se se ela está balanceada, caso não esteja, efetuar rotação (simples ou dupla) até que esteja.
Remoção
• Busca nó mais próximo (igual a qualquer outra árvore de busca binária); • Rotaciona-se até que o mesmo seja um nó-folha e remova-o;
Por quê? A remoção de um nó sem filhos é o caso mais simples!
• Verifique se a árvore se encontra balanceada, caso não esteja, efetue rotações.
Rotação
Operação em que a ordem dos nós em uma árvore de
busca binária é modificada para a manutenção do
balanceamento da mesma;
Pode ser simples (um único passo, rotacionando à
esquerda ou à direita) ou dupla (efetuando mais de uma
vez a rotação, em qualquer combinação de rotações
simples).
Conceitos e Recursos: Árvore Balanceada
Rotação
Rotação Simples:
Ocorre quando o nó desbalanceado e o seu filho estão no
mesmo sentido de inclinação da árvore;
1. Dado um nó X com um filho à direita Y e este tendo um
filho à esquerda Z;
•
Pseudo-código:
Seja Y o filho à direita de X;
Torne X o filho à esquerda de Y;
Torne o filho à esquerda de Y (Z) o filho à direita
Conceitos e Recursos: Árvore BalanceadaAlgoritmos e Estrutura de Dados
Árvores
Rotação a Esquerda
•
Rotação Simples a Esquerda
p aponta para o nó desbalanceado q = right(p);
hold = left(q); left(q) = p;
1. Dado um nó X com um filho à esquerda Y e este tendo
um filho à direita Z;
•
Pseudo-código:
Seja Y o filho à esquerda de X;
Torne X o filho à direita de Y;
Torne o filho à direita de Y (Z) o filho à esquerda
de X;
Conceitos e Recursos: Árvore Balanceada
Rotação a Direita
• Rotação Simples a Direita
p aponta para o nó desbalanceado q = left(p);
Conceitos e Recursos: Árvore Balanceada
Algoritmos e Estrutura de Dados
Rotação SIMPLES
Árvores3 8
4 10
2 6
8
4 10
2 6
3
0 Rotação a direita (nó 8)
0 0 0 4
2 8
10 6
Operação em que a ordem dos nós em uma árvore de
busca binária é modificada para a manutenção do
balanceamento da mesma;
Pode ser simples (um único passo, rotacionando à
esquerda ou à direita) ou dupla (efetuando mais de uma
vez a rotação, em qualquer combinação de rotações
simples);
Conceitos e Recursos: Árvore Balanceada
Rotação
Rotação DUPLA:
Ocorre quando o nó desbalanceado está em um
sentido da inclinação e o seu filho em outro;
Conceitos e Recursos: Árvore Balanceada
Algoritmos e Estrutura de Dados
Rotação DUPLAS
Árvores0 8
4 10
2 6
0
8
4 10
2 6
5
(a) 8
6 10
4
Conceitos e Recursos: Árvore Balanceada
Rotação DUPLAS
8
6 10
4
5 2
(b) 6
4 8
Conceitos e Recursos: Árvore Balanceada
Algoritmos e Estrutura de Dados
Árvores
2
4
6
1 3 5 7
Op. de balanceamento
4
1 6
3 5 7
Inserção: 4, 6, 1, 7, 5, 3 e 2.
Conceitos e Recursos: Árvore Balanceada
Remoção
4
6
7
Remo ver n
ó 2
4
6
7
Op. d
e bala ncea
mento
4
2 6
Conceitos e Recursos: Desempenho
Algoritmos e Estrutura de Dados
Árvores AVL
ÁrvoresO tempo médio para encontrar um elemento em
uma árvore AVL é da ordem de O (log n)
Perguntas, considerações e comentários