AED 2002/2003 p.1/21 Árvores Binárias Estrutura de dados elementar Métodos de travessia de árvores Procura em árvores binárias Manipulação eficiente Exemplos de clientes
AED 2002/2003 p.2/21 Árvores de Procura 5 4 8 2 5 1 Nós na sub-árvore esquerda tem chaves menores ou iguais que a raíz Nós na sub-árvore direita tem chaves maiores ou iguais que a raíz
AED 2002/2003 p.3/21 Travessia de Árvores em Pré-Order Visita a raíz antes dos filhos #include "Item.h" typedef struct node { struct node *l; struct node *r; Item item; *link; void traverse(link h) { if (h == NULL) return; visit(h); traverse(h->l); traverse(h->r);
AED 2002/2003 p.4/21 Travessia de Árvores em In-Order Visita a raíz depois do filho esquerdo e antes do direito Exemplo de aplicação: imprime os nós ordenados #include "Item.h" typedef struct node { struct node *l; struct node *r; Item item; *link; void traverse(link h) { if (h == NULL) return; traverse(h->l); visit(h); traverse(h->r);
AED 2002/2003 p.5/21 Travessia de Árvores em Post-Order Visita a raíz depois dos filhos Exemplo de aplicação: avaliação de expressões posfixadas #include "Item.h" typedef struct node { struct node *l; struct node *r; Item item; *link; void traverse(link h) { if (h == NULL) return; traverse(h->l); traverse(h->r); visit(h);
AED 2002/2003 p.6/21 Versão não Recursiva do Pré-Order void traverse(link h) { STACKinit(max); STACKpush(h); while (!STACKempty()) { visit(h = STACKpop()); if (h->r!= NULL) STACKpush(h->r); if (h->l!= NULL) STACKpush(h->l);
AED 2002/2003 p.7/21 Algumas Operações em Árvores Count: conta os nós da árvore Height: conta a profundidade da árvore int count(link h) { if (h == NULL) return 0; return count(h->l) + count(h->r) + 1; int height(link h) { int u, v; if (h == NULL) return -1; u = height(h->l); v = height(h->r); if (u > v) return u+1; else return v+1;
AED 2002/2003 p.8/21 Pesquisa em Árvores Binárias (BST) Inserção de um item Procura por dada chave Apagamento de um item Aplicações: Tabelas de símbolos Dicionários para tradução de termos
Pesquisa em Árvores #include <stdlib.h> #include "Item.h" typedef struct STnode* link; struct STnode { Item item; link l, r; int N ; static link head, z; link NEW(Item item, link l, link r, int N) { link x = malloc(sizeof *x); x->item = item; x->l = l; x->r = r; x->n = N; return x; void STinit() { head = (z = NEW(NULLitem, 0, 0, 0)); int STcount() { return head->n; Item searchr(link h, Key v) { Key t = key(h->item); if (h == z) return NULLitem; if eq(v, t) return h->item; if less(v, t) return searchr(h->l, v); else return searchr(h->r, v); AED 2002/2003 p.9/21
AED 2002/2003 p.10/21 Pesquisa em Árvores Item STsearch(Key v) { return searchr(head, v); link insertr(link h, Item item) { Key v = key(item), t = key(h->item); if (h == z) return NEW(item, z, z, 1); if less(v, t) h->l = insertr(h->l, item); else h->r = insertr(h->r, item); (h->n)++; return h; void STinsert(Item item) { head = insertr(head, item);
AED 2002/2003 p.11/21 Operações de rotação A E E C S A S C R X R X link rotr(link h) { link x = h->l; h->l = x->r; x->r = h; return x; link rotl(link h) { link x = h->r; h->r = x->l; x->l = h; return x;
AED 2002/2003 p.12/21 Selecção com árvores binárias Selecciona a k ésima chave Item selectr(link h, int k) { int t = h->l->n; if (h == z) return NULLitem; if (t > k) return selectr(h->l, k); if (t < k) return selectr(h->r, k-t-1); return h->item; Item STselect(int k) { return selectr(head, k);
AED 2002/2003 p.13/21 Partição de Árvores Binárias Selecciona a k ésima chave e coloca-a na raiz link partr(link h, int k) { int t = h->l->n; if (t > k ) { h->l = partr(h->l, k); h = rotr(h); if (t < k ) { h->r = partr(h->r, k-t-1); h = rotl(h); return h;
AED 2002/2003 p.14/21 Remoção de nós em Árvores Binárias link joinlr(link a, link b) { if (b == z) return a; b = partr(b, 0); b->l = a; return b; link deleter(link h, Key v) { link x; Key t = key(h->item); if (h == z) return z; if (less(v, t)) h->l = deleter(h->l, v); if (less(t, v)) h->r = deleter(h->r, v); if (eq(v, t)) { x = h; h = joinlr(h->l, h->r); free(x); return h; void STdelete(Key v) { head = deleter(head, v);
AED 2002/2003 p.15/21 Inserção na raiz Insere novo nó na raiz da árvore Usa rotações para deslocar novo nó para a raiz link insertt(link h, Item item) { Key v = key(item); if (h == z) return NEW(item, z, z, 1); if (less(v, key(h->item))) { h->l = insertt(h->l, item); h = rotr(h); else { h->r = insertt(h->r, item); h = rotl(h); return h;
AED 2002/2003 p.16/21 Pesquisas em BST Geralmente eficiente: O(log N) No pior caso, O(n) para uma árvore desequilibrada: Ordem de inserção: 1,2,3,4,5,6,7,8 No caso de chaves aleatórias, O(log N) Comparação com pesquisa binária em tabelas: Tempo de pesquisa comparável Tempo de inserção muito mais rápido Tempo de pesquisa e inserção são O(N) no pior caso (árvore degenerada)
AED 2002/2003 p.17/21 Árvores Binárias Equilibradas Evitam o pior caso de O(N) Algum overhead na construção Alternativa: Requilibrar uma árvore, depois de construída Usar aleatoriedade Usar técnicas especiais de construção (Red-Black trees, etc)
AED 2002/2003 p.18/21 Balanceamento de uma Árvore Binária Equilibra uma árvore Usa a operação de partição para colocar a mediana na raíz link balancer(link h) { if (h->n < 2) return h; h = partr(h, h->n/2); h->l = balancer(h->l); h->r = balancer(h->r); return h;
AED 2002/2003 p.19/21 Uso de aleatoriedade Se as chaves forem uniformemente distribuídas, um novo nó fica na raíz com probabilidade 1/(1+N) Quando se insere um nó, coloca-se na raíz com probabilidade 1/(1+N) link insertr(link h, Item item) { Key v = key(item), t = key(h->item); if (h == z) return NEW(item, z, z, 1); if (rand()< RAND_MAX/(h->N+1)) return insertt(h, item); if less(v, t) h->l = insertr(h->l, item); else h->r = insertr(h->r, item); (h->n)++; return h; void STinsert(Item item) { head = insertr(head, item);
link RBinsert(link h, Item item, int sw) { Key v = key(item); if (h == z) return NEW(item, z, z, 1, 1); if ((hl->red) && (hr->red)) { h->red = 1; hl->red = 0; hr->red = 0; if (less(v, key(h->item))) { hl = RBinsert(hl, item, 0); if (h->red && hl->red && sw) h = rotr(h); if (hl->red && hll->red) { h = rotr(h); h->red = 0; hr->red = 1; else { hr = RBinsert(hr, item, 1); if (h->red && hr->red &&!sw) h = rotl(h); if (hr->red && hrr->red) { h = rotl(h); h->red = 0; hl->red = 1; fixn(h); return h; AED 2002/2003 p.20/21 Árvores Red-Black
Árvores Red-Black AED 2002/2003 p.21/21