Você está na página 1de 40

Algoritmos e Estrutura de Dados III

Plano de ensino da disciplina: 30.705-0 Departamento: 03 Carga horria: 60 horas EMENTA: Estrutura de dados dinmicas: tipos de rvores e suas aplicaes, implementao de ndices utilizando rvores e sua interao com arquivos de dados, tipos de arquivos, compresso, grafos, estudo de implementaes. OBJETIVOS: Capacitar o aluno na avaliao e no projeto de quaisquer estruturas de dados que utilizam rvores. Operaes com arquivos e implementao de ndices com rvores, correo e eficincia das implementaes. RELAO DOS CONTEDOS: - Conceituao de estruturas de dados tipo rvores: tree, tree C, AVL, etc.; - Estrutura de dados tipo rvores binrias, implementao utilizando TAD com modalidade em ponteiros. - Conceituao de estrutura de dados tipos rvore B, B+, aplicaes de rvore B e B+. Implementaes de ndices - Arquivos x ndices, pesquisa em tabelas: Arquivos sequenciais, sequenciais indexados, indexados e endereo por clculo (Hashing); - Tcnicas de compresso de arquivos. - Conceituao de grafos em computadores, aplicaes de grafos, implementao de grafos; BIBLIOGRAFIA BSICA (LIVROS TEXTOS): TENEMBAUM, Aaron M. Estrutura de Dados Usando C. So Paulo: Makron Books do Brasil, 1995. PEREIRA, Slvio Lago. Estruturas de Dados Fundamentais: Conceitos e Aplicaes. So Paulo: Ed. rica, 1996. VELLOSO, Paulo. Estruturas de Dados. Rio de Janeiro: Ed. Campus, 1991. VILLAS, Marcos Vianna & Outros. Estruturas de Dados. Conceitos e Tcnicas de implementao. Rio de Janeiro: Ed. Campus, 1993. BIBLIOGRAFIA COMPLEMENTAR (LIVROS REFERENCIADOS): HOLZNER, Steven. Fundamentos de Estruturas de Dados. 3 ed. Rio de Janeiro: Ed. Campus, 1987. HOROWITZ, Ellis. Fundamentos de Estruturas de Dados. 3 ed. Rio de Janeiro: Ed. Campus, 1987. SZWARCFITER, JAIME LUZ. Estruturas de Dados e seus Algoritmos. Rio de Janeiro: Ed. LTC, 1994. 30 / 30 horas Algoritmos e Estrutura de Dados III Engenharias e Cincia da Computao Crditos: 04

rvores
Alm das filas e pilhas vistas no semestre anterior, que eram estruturas lineares, existem outras formas usadas para representar os dados, que so chamadas genericamente de no-lineares. Essa representao permite que sejam feitos outros tipos de relaes entre os dados, como por exemplo, relao de hierarquia. Um dos exemplos mais significativos de estruturas no lineares que representam as relaes de hierarquia a rvore. Uma rvore pode ser definida como um conjunto de ns (ou nodos), tais que: existe um n denominado raz da rvore os demais ns formam subconjuntos distintos S1,S2,...Sm, onde cada subconjunto desses uma rvore. Esses subconjuntos recebem a denominao de sub-rvores. Um exemplo bem conhecido de relao de estruturao em rvore a estruturao de um livro, que subdividido em captulos, onde cada captulo subdividido em sees, que por sua vez, possuem tpicos.
rvores Introduo
rvores Binrias

rvores

Conceito

Percurso

Balanceamento

Considere agora o seguinte exemplo de rvore genealgica

Pedro Marcelo

Maria

Andr

Rodrigo

Mrcia

Viviane

Czar

Aide

Cludio

Analisando essa rvore, podemos concluir: Essa rvore possui 10 ns distribudos aleatoriamente. O nodo Pedro a raiz da rvore, que tem 3 sub-rvores com Maria, Andr e Marcelo como razes. O nmero de sub-rvores de um n determina o grau desse n. Dessa forma, Pedro e Maria tm grau 3, enquanto Andr tem grau 2 e Marcelo tem grau zero. Nodos que tem grau zero so denomidados terminais ou folhas.
Pergunta: Qual o grau do nodo Viviane?
Apostila de Algoritmos e Estrutura de Dados III 2

Considerando que cada n tem um grau mximo (nmero de sub-rvores das quais esse n raiz) e que todos os ns possuem o mesmo grau mximo, definimos esse grau como o grau da rvore. Uma rvore homognea quando todos os seus nodos possuem as mesmas caractersticas de contedo, ou seja, o mesmo tipo de informao; caso contrrio ela ento chamada de rvore heterognea. Para identificar os ns da estrutura, usamos as denominaes da relao de hierarquia existente em uma rvore genealgica. Dessa forma, Pedro pai de Maria, Andr e Marcelo que so irmos entre si. No sentido inverso, Rodrigo, Mrcia e Viviane so filhos de Maria e netos de Pedro. Para conhecermos os antepassados de um nodo, basta identificarmos todos os nodos ao longo do caminho entre a raz e este nodo. Ex: os antepassados de Cludio so, na ordem: Pedro, Maria e Viviane. Um conceito importante no estudo de rvores o conceito de nvel, que representa a distncia do nodo at a raiz. Por definio, a raiz da rvore tem nvel 0. Na figura anterior, os nodos Maria, Andr e Marcelo tm nvel 1, os nodos Rodrigo, Mrcia, Viviane, Czar e Aide tem nvel 2, assim por diante. O nodo de maior nvel nos fornece a altura (ou profundidade) da rvore.
Pergunta: No exemplo que estamos usando, a rvore tem altura (???)?

Exerccio : Tente construir uma rvore com base nas informaes abaixo: - O nodo C tem grau 3. - O nodo X neto de C e filho de B. - O av de B A. - O nodo A tem altura 0 e T tem altura 1. - Os antepassados de P so A,T e K, que so tambm antepassados de H. - T tem grau 2, e um dos seus filhos o nodo S. - O nodo G tem 2 sub-rvores que so netos de C. - D irmo de G, e uma folha. - E e F tem graus 0 e 1 respectivamente e so tambm netos do nodo C. - O nodo N tem nvel 4.

Representaes das rvores


comum a utilizao da representao cima-baixo devido sua popularidade, porm, uma rvore pode ser representada tambm de outras maneiras:

Representao natural de uma rvore:


K E F G H I J

Apostila de Algoritmos e Estrutura de Dados III

Representao por endentao:

A B E F C G D H K I J

Representao por conjuntos A B E F C H G K I J D

Representao por nvel: ( A (B) (C) (D) ) ...

rvores Binrias e variantes


Definio: uma rvore binria se caracteriza pelo fato de todos os seus nodos terem no mximo duas sub-rvores, ou seja uma rvore de grau 2. As duas sub-rvores de cada n so denominadas subrvore esquerda e sub-rvore direita. Na figura abaixo, temos duas rvores binrias, sendo a da esquerda, incompleta e a da direita completa: A B D F C D B E F A C G

No segundo caso, cada nodo possui dois descendentes, exceto as folhas, que por definio no tem filhos. Geralmente nos referimos aos filhos de um nodo numa rvore binria como sendo da esquerda ou da direita, de acordo com o posicionamento dele. Converso de uma rvore de um grau qualquer para uma rvore binria: Supomos que temos um nodo A com 3 descendentes diretos, B C e D, etc. Deve-se ento fazer o seguinte:
Apostila de Algoritmos e Estrutura de Dados III 4

- A raiz torna-se a raiz de uma rvore binria. - B torna-se o descendente da esquerda de A - C torna-se o descendente da direita de B. - D torna-se o descendente da direita de C. - E torna-se o descendente da direita de D. A B C A B E F C H A B E F G C H I D J I D J D

Exerccios: transforme as seguintes rvores em rvores binrias: Representaes alternativas (no computador): Existem duas maneiras alternativas de representarmos rvores binrias no computador: - em listas lineares e - em listas encadeadas. a) rvores binrias em listas lineares: Uma maneira de representar uma rvore binria numa lista linear consiste em declarar um vetor com tamanho mximo igual ao nmero mximo de ns da rvore binria. A representao de rvores binrias na forma de listas lineares especialmente indicada quando as rvores so completas, pois resulta na utilizao mxima do espao alocado. A representao na forma de uma lista linear no indicada em duas situaes: - quando for necessrio efetuar operaes de insero e retirada de nodos, pois potencialmente exigir uma grande movimentao dos dados para conseguir o efeito desejado; e - quando a rvore afasta-se mais e mais da condio de completa, ou seja, no indicada em situaes onde a estrutura de dados frequentemente alterada.

rvore binria completa alocada sequencialmente.

rvore binria incompleta alocada sequencialmente


5

Apostila de Algoritmos e Estrutura de Dados III

Nesse tipo de representao, fica difcil saber qual o ascendente de um tomo e embora geralmente adequada para a maioria das aplicaes, poder haver sempre desperdcio de espao. Na alocao encadeada subdividimos o espao de um n em trs campos, como mostrado abaixo:
nodo Pos sub-rvore esquerda Pos sub-rvore direita

Veja abaixo, a representao da seguinte rvore:

Outra forma de representar a rvores seria no seguinte formato


Link esquerdo Nodo Link direito

A rvore ento, seria apresentada da seguinte forma:

Operadores para rvores binrias: Donald E. Knuth popularizou trs ordens de percurso em rvores binrias: Pr-ordem ou prefixa, simtrica ou infixa e Ps-ordem ou ps-fixa. Prefixa: visita a raiz visita a sub-rvore esquerda visita a sub-rvore direita

Infixa:
visita a sub-rvore esquerda visita a raiz visita a sub-rvore direita

Posfixa:
visita a sub-rvore esquerda visita a sub-rvore direita visita a raiz

Considerando a rvore apresentada ao lado, veja a seqncia de nodos visitados de acordo com cada ordem de visitao: A
Visitao prefixa: A,B,D,E,C,F,G Visitao infixa: D,B,E,A,F,C,G Visitao posfixa: D,E,B,F,G,C,A

C D E F

B G

Apostila de Algoritmos e Estrutura de Dados III

Exerccios:
1) Dada as seguintes rvores, faa para cada uma delas a visitao dos nodos utilizando a ordem prefixa, infixa e psfixa

a) C D H I E

A B F G

b) C D H I M E K

A B F J L G

c) C D H I E

A B F G K L M J

rvores de Expresses

Uma expresso aritmtica pode ser armazenada sob a forma de uma rvore binria, onde as razes armazenariam as operaes a serem efetuadas, e as sub-rvores esquerda e direita armazenariam os operandos a serem usados. Por exemplo, a expresso a+b deveria ento ser apresentada com a seguinte forma:

+ A B

J no caso da expresso a + b * c, a prioridade dos operadores e a ordem de ocorrncia, ambos, devem ser respeitados

+ A B * C

ou seja, ao se percorrer as rvores na forma infixa e posfixa respectivamente teremos: a,+,b,*,c e a,b,c,*,+, que diferente da expresso b * c + a, que seria representada assim:

+ * B C A

Apostila de Algoritmos e Estrutura de Dados III

Aps estas anlises, a expresso ((A+B)/C)*(D-E), ento, seria representada assim:

* / + A B C D E

Como dica para resolver uma rvore completa, procure sempre resolver as expresses do centro para fora. No caso anterior, por exemplo, represente: A+B /C D-E *

Exerccios:
Transforme as seguintes expresses para posfixa utilizando rvores binrias para fazer a transformao: a) (a+b) * (c-d) b) (a+b*c)*a + (c-d)*3 c) (a+b*c)*a 4*(5-6+1) + (c-d)*3 d) (a+b-c) (3-4)*(5-6+1) + (c-d*3)

rvore binria de pesquisa


Uma rvore binria, cuja raiz armazena o elemento R, denominada rvore binria de pesquisa se: todo elemento armazenado na sub-rvore esquerda menor do que R, todo elemento armazenado na sub-rvore direita maior do que R. Uma rvore binria de pesquisa, visitada em ordem simtrica/infixa (E,R,D), resulta em uma lista de dados em ordem crescente. Veja os casos abaixo: na rvore Y, todos os elementos da sub-rvore esquerda (a,b,c) so menores que a raiz, e nenhum elemento da sub-rvore direita (e,f,g) menor que a raiz. Entretanto, ela no uma rvore binria de pesquisa, pois na sub-rvore da direita, cuja raiz G, tem uma sub-rvore direita que armazena uma informao menor que a raiz.

X) Ordenada (binria de pesquisa) D B A C D E F

Y) No ordenada D B A C E G F

A rvore abaixo, binria de pesquisa? D A C B F


Apostila de Algoritmos e Estrutura de Dados III 8

E G

Formato dos nodos a serem empregados na organizao dos dados: Cada nodo precisa armazenar um elemento e referenciar duas sub-rvores: Trabalho (parte 1): Implementar as seguintes operaes sobre uma A. B. P.: - Insero em uma ABP: - Busca de 1 elemento na ABP: - Remoo de 1 elemento da ABP: - Listagem da rvore na forma: Em nvel: Prefixa: Infixa: Posfixa: - Rotina para det. o > elemento da ABP: - Rotina para det. a altura da ABP: Fornecido ? ? opcional ? Fornecido ? ? opcional

Obs: - as rotinas ? devem ser desenvolvidas pelo aluno. - As rotinas opcionais valero meio ponto extra no trabalho - O programa deve ainda apresentar um menu para que seja selecionada a opo desejada. Bibliografia Recomendada: TENEMBAUM, Aaron M. e.. Estruturas de Dados Usando C. SP.: Ed. McGraw-Hill, 1995. PEREIRA, Slvio do Lago. Estruturas de Dados Fundamentais: Conceitos e Aplicaes. SP.: Ed. rica, 1996.

Apostila de Algoritmos e Estrutura de Dados III

Cdigo Fornecido (em C++), base para compreenso da manipulao em rvore


# include <iostream> using namespace std; class nodo { private: nodo *esq; char info; nodo *dir; public: void ins (nodo* *T, char informacao); void infixa (nodo* *T); }; nodo *P; void nodo::ins (nodo* *T, char informacao){ cout << *T ; if (*T == NULL) { *T = new nodo; //pode-se verificar aqui se a (*T) == NULL para inserir (*T)->esq = NULL; (*T)->info = informacao; (*T)->dir = NULL; cout << "ins. no " << (*T) <<" "<< (*T)->esq <<" "<< (*T)->info <<" "<< (*T)->dir << endl; } else{ if (informacao < (*T)->info) { ins (&((*T)->esq), informacao); } else{ ins (&((*T)->dir), informacao); } } } void nodo::infixa (nodo* *T){ if ((*T) != NULL) { infixa (&(*T)->esq); cout << (*T) << " " << (*T)->esq << " " << (*T)->info << " " infixa (&(*T)->dir); } } int main (void) { nodo *T; T = NULL; cout << &T << cout << &T << cout << &T << cout << &T << cout << &T << cout << &T << cout << &T << cout << &T <<

<< (*T)->dir << endl;

" " " " " " " "

"; "; "; "; "; "; "; ";

T->ins T->ins T->ins T->ins T->ins T->ins T->ins T->ins

(&T, (&T, (&T, (&T, (&T, (&T, (&T, (&T,

'd'); 'c'); 'a'); 'h'); 'e'); 'i'); 'g'); 'f');

cout << endl << "Infixa: T->infixa (&T); return(0);

" << endl;

Apostila de Algoritmos e Estrutura de Dados III

10

a) Insero em uma A. B. P.:


Inserir um elemento X em uma rvore Binria de Pesquisa vazia trivial. Se a rvore no se encontra vazia deve-se fazer o seguinte: Compara-se o elemento a inserir com o elemento raiz da rvore. Se o elemento for menor, o inserimos na subrvore esquerda, seno, o inserimos na sub-rvore direita.
Insere (nodo *T , char inform) incio se T = NULO ento novo(T) T->esq = NULO T->info = inform T->dir = NULO seno se inform < T->info ento Insere(T->esq,inform) seno Insere(T->dir,inform) fim_se fim_se fim

Representao interna de uma rvore binria ( com ponteiros)

Para entendermos o funcionamento do algoritmo de insero, veja o exemplo de construo de uma rvore binria de pesquisa com o conjunto de nmeros {17,99,13,1,3,100,400} raiz nulo 17 17 17 17 raiz 17 99 13 99 13 1 3 99 100 400

Anlise DETALHADA do procedimento de insero: Considere como exemplo a rvore B abaixo, que foi inserida atravs das linhas de programa apresentadas ao lado dela. Note que para criar a rvore, os nodos devem ser inseridos sempre por nvel, do nvel 0 ao nvel n ou na ordem prefixa, pois para inserir o C, por exemplo, j deve ter sido inserido anteriormente o nodo E. Para inserir o F, j deve ter sido inserido anteriormente o nodo H, e assim por diante
E 13 C A F G H
nodo *T;
T = NULL; T->ins T->ins T->ins T->ins T->ins T->ins T->ins (&T, (&T, (&T, (&T, (&T, (&T, (&T, 'e'); 'c'); 'a'); 'h'); 'f'); 'i'); 'g');

S para recordar, consideramos um programa que cria e atribui um ponteiro, por exemplo:
char *x; *x='a'; Neste caso: x = FFF4 &x=FFF0 e *x = 'a' FFF0 X FFF4 FFF4 a

Apostila de Algoritmos e Estrutura de Dados III

11

Com a anlise da estrutura da rvore na memria do computador, aps a insero de todos os nodos, obtm-se uma tabela que apresentada abaixo. Para gerar tal tabela, basta incluir a seguinte linha na rotina infixa():
cout << (*T) << " " << (*T)->esq << " " << (*T)->info << " " << (*T)->dir << endl;

T (& de quem aponta para o nodo) FFF4 09FE 0A08 0A01 0A12 0A29 0A15

*T

(*T)->esq que informao tenho no cpo esq

(*T)->dir que informao tenho no cpo dir 0A12 ----- (NULL) ----0A30 0A3A --------?T FFF4

(*T)->info que informao tenho no cpo info E C A H F G I


E 13 C H

09FE 0A08 0A1C 0A12 0A26 0A3A 0A30

0A08 0A1C ----0A26 -------------

Estrutura do Nodo:
(*T)->esq (*T)->info (*T)->dir 1 byte 2 bytes 1 byte

FFF4 &(*T) 09FE *T 09FE 0A08 09FF 0A00 E

0A01 0A12 0A12 0A26

A
0A13 0A14 H 0A15 0A30

F G

0A08 0A1C 0A1C 0A1D 0A1E A

0A09 0A0A C 0A1F -

0A0B 0A26 -

0A27 0A28 F

0A29 0A3A 0A3A -

0A30 -

0A31 0A32 I 0A3D -

0A33 -

0A3B 0A3C G

b) Pesquisa em uma rvore binria


Se a rvore for nula, nada a fazer, caso contrrio, o processo de busca o mesmo utilizado para insero.
Void procura (...){ if (*T ==NULL) printf (Nodo no existe!); else { if( informacao < (*T)->info) procura ( usando sub-rvore esquerda) // procura para a esquerda else { if (informacao > (*T)->info) procura ( usando sub-rvore direita) // procura para a direita else // encontrou } } }

Apostila de Algoritmos e Estrutura de Dados III

12

c) Retirada em uma A. B. P.:


Se o nodo a ser retirado de uma rvore for uma folha, basta atualizar o link do seu pai para que no aponte mais para o n a ser retirado. No caso de retirada de um nodo que raiz, deve-se adotar o seguinte procedimento: - se a raiz no tem filho esquerdo, o filho direito passa a ser a raiz, e vice-versa -se a raiz tem ambos os filhos, pode-se optar por buscar a > chave esquerda ou a < chave direita para ser a nova raiz: Exerccio: Remover o D:

D B A C E F G

Anlise do procedimento de retirada Considere como exemplo a rvore B abaixo (a mesma que foi utilizada para explicar o procedimento de insero)
E 13 C A F G H

So quatro as possibilidades existentes para retirada. Considere que o nodo a ser retirado pode ser: a) Um nodo sem descendentes b) Um nodo sem descendentes na direita mas com descendentes na esquerda. c) Um nodo sem descendentes na esquerda mas com descendentes na direita. d) Um nodo com 2 filhos. No programa, isso pode ser representado por 4 testes de seleo (if)
if } if } if } if } ((*T)-> esq != NULL) && ((*T)-> dir ==NULL){ ... (1 linha) ((*T)-> esq == NULL) && ((*T)-> dir !=NULL){ ... (1 linha) ((*T)-> esq == NULL) && ((*T)-> dir ==NULL){ ... (1 linha) ((*T)-> esq != NULL) && ((*T)-> dir != NULL){ ... (algumas linhas) //somente descendentes na esq.

//somente descendentes na dir.

//nodo sem descendentes.

//nodo com 2 filhos

No caso da retirada de uma folha (A, G ou I), (item a) o procedimento a ser realizado muito simples: Simplesmente atribui nulo (NULL) para o ponteiro que est apontando para o nodo a ser retirado e libera-se a memria ocupada anteriormente pelo nodo.
Apostila de Algoritmos e Estrutura de Dados III 13

E 13 C A F G H 13 C

E H

F G

No caso da retirada de um nodo com um filho (item b ou c), simplesmente o nodo pai passa a apontar para o neto. Exemplos:
E E 13 C A F G G H 13 A I F I H

E 13 C A F G H A 13 C

E H

No caso da retirada de um nodo com um ambos os filhos (item d), deve-se criar uma rotina aqui chamada de pega_maior ou Get_max, que dever pegar o maior elemento da sub-rvore que est sendo excluda:
E 13 C A F G H A 13 C F G E E H A 13 C F G E G

Neste caso, como o Get_max deve ser aplicado sobre a sub-rvore esquerda do H, o valor a retornar pela funo ser o G
A

13 C F

Apostila de Algoritmos e Estrutura de Dados III

14

Se, por exemplo, tivesse um F2 pendurado na esquerda do G, aps a retirada do G ele deveria aparecer pendurado na direita do F
E 13 C A F G F2 H 13 C I A F F2 E G

Abaixo apresentado o algoritmo para excluso:


Procedure exclusao(...) incio se (*T ==NULL) exit; // elemento no foi encontrado se (informacao == T->info) // elemento encontrado na raiz P=t; se (T->esq == NULL) T=T->dir // A raiz no tem filho esquerdo seno se (T->dir=NULL) T=T->esq seno P = PegaMaior(T->esq); T->info = P->info; fim_se libera(P); fim_se seno se (informacao < T->info) ento // elemento encontrado numa das sub-rvores exclusao(T->esq,informacao) seno exclusao(T->dir,informacao) fim_se fim_se fim

d) Listagem em uma rvore Binria


Conforme visto anteriormente, podemos percorrer uma rvore passando por todos os nodos dela. Existem 4 formas de atravessamento (listagem) de uma rvore:
- Prefixa (?) - Posfixa (?) Infixa(...); incio se (T != nil) infixa(t->esq); escreve(T->.info,','); infixa(t->.dir); fim_se fim

Rotina para pegar o maior elemento de uma rvore ( Pega_maior): O maior elemento de uma rvore binria ordenada encontra-se sempre no nodo que estiver mais direita possvel na rvore. Apostila de Algoritmos e Estrutura de Dados III 15

Trabalho 1 de Algoritmos e Estrutura de Dados 3


1. Introduo e Objetivos:
Este trabalho tem por objetivo verificar a aplicao de rvores binrias de pesquisa para a resoluo de problemas comuns no mbito da Cincia da Computao.

2. Descrio do trabalho
O trabalho, que poder ser realizado por duplas ou grupos de at 3 alunos (no mximo) consiste em duas etapas: a) implementao das rotinas de: - Insero em uma ABP - Busca de 1 elemento na ABP: - Remoo de 1 elemento da ABP: - Listagem da rvore na forma prefixa, infixa e posfixa - Rotina para det. o maior elemento da ABP: b) Aplicao prtica da rvore Binria de Pesquisa:

Dicionrio de 1 Segundo de Andy.


Andy est com 9 anos e ficando ambicioso. Ele quer criar um programa que extraia palavras de um texto, at mesmo as palavras com hfens e listar todas as palavras encontradas no texto em ordem alfabtica. A entrada para o programa seria um texto com no mximo 500 palavras, terminado com um EOF. O papel do grupo (vocs) criar um programa que liste todas as distintas palavras que existirem no texto em ordem alfabtica, todas convertidas em minsculas. Letras tambm so consideradas. Palavras como ma, Ma, MA ou Ma devem ser consideradas como a mesma palavras e serem gravadas no dicionrio como ma. E existe ainda um detalhe: se acontecer no texto a separao devido uma troca de linha, o programa dever entender a palavra. Vamos ao exemplo.

Arquivo de entrada (entrada.txt):


E ento o padre guardava a sua coleo dentro do GUaRDa-RoUpA, ficando de guarda para que ningum a roubasse.

Arquivo de sada (sada.txt)


a coleo de dentro do e ento ficando guarda guarda-roupa guardava ningum o padre para que roubasse sua Dica para implementao: deve-se fazer um programa que leia o texto de entrada inserindo cada palavra lida em uma rvore binria de pesquisa, no caso da palavra ainda no se encontrar na rvore. Aps o trmino do arquivo de entrada, deve ser gerado um arquivo de sada com as palavras ordenadas, bastando para isso percorrer a rvore binria de pesquisa de forma infixa. * O idem b) deste trabalho foi tirado do conjunto de problemas mantidos pela Universidade de Valladolid, sob nmero 10815.

Apostila de Algoritmos e Estrutura de Dados III

16

Exerccios
1 Construa uma rvore com base nas informaes abaixo:

O nodo B tem grau 3. O nodo K neto de B e um de seus filhos F. O av de S A. O nodo K tem um irmo. O nodo Pai de T o nodo U. O filho de A, que nodo irmo de B, tem dois filhos, sendo que um deles o nodo P. O nodo T tem altura 3, mas no neto de B, tampouco filho de P. Os nodos T e C esto no mesmo nvel. O nodo A tem altura 0, e o nodo D tem altura 1. A rvore tem altura 4, Os nodos X e Y tem grau 0.

2. Transforme as rvores do exerccio 1 para rvore binria. 3. Represente as rvores do exerccio 2 em uma estrutura de dados atravs de 3 vetores: ELOE, NODO e ELOD. 4. Faa o caminhamento prefixo, infixo e ps-fixo para as rvores do exerccio 4. 5. Represente a expresso (A*B^C+(2/A)*B-3*C/(2*A)) atravs de uma rvore, forma infixa. 6. Sejam ABCDEFGHI e DACBFGFIJ as seqncias infixa e prefixa de uma rvore de Busca Binria T, reconstrua graficamente a rvore T. 7. Construa uma ABB com o conjunto de nmeros: {100,23,13,15,66,43,134,87,166,786,214,221,7,1880,200} 8. Faa o balanceamento da rvore 7 e apresente-a graficamente

Apostila de Algoritmos e Estrutura de Dados III

17

Trabalho (parte 2):


As rvores so timas para implementar indexao, pois aceleram o processo de pesquisa de informaes. Acesso em disco sempre mais lento do que acesso em memria. Excluses e incluses mantendo os dados de um arquivo ordenado, por exemplo, implicariam na movimentao de uma grande quantidade de dados, sendo um processo excessivamente lento para ser utilizado em aplicaes prticas. A utilizao de ndices tem por objetivos: rapidez no processo de incluso de novos registros rapidez no processo de pesquisa do arquivo rapidez no processo de atualizao do arquivo A incluso em um arquivo de dados ser sempre efetuada no final do arquivo, sendo ento um procedimento fcil de implementar. Para garantir ento rapidez de pesquisa, uma estrutura de indexao reduziria em muito os acessos a disco. O ndice seria um mapeamento que associa cada chave da rvore de ndice a uma chave no arquivo de dados. A atualizao utilizando ndices tambm muito eficiente. Se um registro deve ser alterado, podemos encontr-lo rapidamente. Se um registro deve ser removido basta remover a sua referncia no ndice (remoo lgica). A remoo definitiva do registro do arquivo pode ser feita em um processo de reorganizao posterior, realizado esporadicamente. Uma base de dados indexada ento composta por duas partes bsicas: um arquivo de dados e uma estrutura de ndice associada. Segue exemplo de uma estrutura de ndice utilizando ABP, onde a chave de ndice o campo nome: T (ponteiro)

Elisa Caio 1

0 Gilda 11

Ana

Denis

Fbio

12

Valdo

10

Bia

8 Hlio

Joo 19

14

A estrutura do arquivo de dados apresentada a seguir:


Registro E# 0 1
... ... ...

Cdigo 12 Elisa 4 Caio

Nome

Telefone 9999-2222 520-9091

Endereo R. Gois, 14 Av. P. P. de Souza, 124, Ap 301


...

Cidade Erechim Erechim


...

UF RS RS
...

...

...

11

26 Gilda

321-3675

Erechim

RS

A estrutura da rvore de indexao seria:


struct tiponodo { struct tiponodo *esq; char nome[10]; int pos; struct tiponodo *dir; }; typedef struct tiponodo *NODO;

A Implementar:
Implemente o programa agenda que a manipulao de um arquivo de dados com a estrutura apresentada acima e ndice por nome. O programa deve apresentar as seguintes opes: Incluir Excluir Consultar dados pelo Nome da pessoa Listar em ordem Alfabtica

Apostila de Algoritmos e Estrutura de Dados III

18

rvores de busca Multidirecionais


Uma ABP no vivel para implementao em disco, pois a busca de cada nodo requer um acesso a disco. Se agruparmos vrias chaves em cada nodo, reduzimos o tempo de pesquisa. Esse agrupamento reduz a altura da rvore. Ex:

ABP
500

420

800

180 150 300

480 455 499

720 515 798 850

980 995

112 110

190

536

987

245

670

A implementao com agrupamento de chaves chamada rvore de busca Multidirecional ou rvore de busca Mvias, e uma rvore de grau M. Em uma rvore de ORDEM M, cada nodo tem M ou menos subrvores. --> Um nodo com 2 chaves = 3 subrvores (Ordem 3) --> Um nodo com 3 chaves = 4 subrvores (Ordem 4) --> Um nodo com 4 chaves = 5 subrvores (Ordem 5) Alguns aspectos das rvores multidirecionais abaixo: - Na rvore (a), os nodos A,D,E,G so completos e B, C, F e H so incompletos. - Um nodo com pelo menos uma subrvore vazia denominado semifolha: (a): b at h. (b): B at G e I at R. - A rvore (a) e a rvore (b) no so balanceadas, porque diferentemente das ABPs, que podem ter folhas em nveis diferentes, uma rvore multidirecional s ser balanceada se todas as folhas se encontrarem no mesmo nvel.

Ordem: Balanceada(s/n): Ordem: Balanceada(s/n):

Apostila de Algoritmos e Estrutura de Dados III

19

Ordem: Balanceada(s/n):

Insero em uma rvore multidirecional balanceada de ordem 3

rvores B
Devido ao pouco desperdcio, as rvores B (ou variaes dela) so utilizadas com muita freqncia em sistemas de arquivos reais. Uma rvore B de ordem M uma rvore de busca multidirecional balanceada que: - cada nodo tem no mximo M-1 chaves e a raiz tem no mnimo 1 chave - cada nodo no-raiz tem no mnimo (M-1)/2 chaves ( ordem 11 tem no mnimo 5 chaves /nodo; ordem 4: mnimo 1) - todas as folhas devem estar no mesmo nvel * Alguns autores consideram que uma rvore de ordem 4 possa ter 4 chaves e 5 filhos em cada nodo. Outros ainda consideram a ordem como n/2, ou seja, uma rvore de ordem 2 possa ter 4 chaves por nodo e 5 filhos. -> Como em Tenembaum 95, de forma coerente, consideraremos Ordem como sendo o Grau mximo da rvore (nmero mximo de filhos por nodo). Nvel Nodos 0 1 2
...

Mnimo Chave 1 2*q 2*q*(q+1) 1 m m


2

Mximo Nodos m-1 (m-1)*m (m-1)*m2 Chaves

1 2 2* (q+1)

sendo que q = (m-1)/2 Apostila de Algoritmos e Estrutura de Dados III 20

Por exemplo, considerando uma rvore de Ordem 4, qual o nmero mnimo e mximo de nodos que ela pode ter nos nveis 0, 1 e 2 respectivamente? E no total? Mostre graficamente. Comparando com uma rvore binria qualquer de 3 nveis (0-2), qual o nmero mximo de chaves que ela poderia ter?

Insero em uma rvore B


A seguir, so mostrados alguns passos para insero em rvores B. Deve-se observar a diviso que ocorre em um nodo quando o nmero de chaves ultrapassa o nmero de nodos permitidos. Se a ordem da rvore for par, as n-1 chaves, excluindo a chave do meio devem ser divididas em 2 grupos de tamanhos diferentes: um grupo com tamanho n/2 e outro grupo com tamanho (n-1)/2.O segundo grupo sempre de tamanho (n-1)/2 independentemente do fato de n ser mpar ou par, pois quando n impar, (n-1)/2 ser igual a n/2. Como exemplo, considere duas rvores, de ordem 4 e 5 respectivamente. Veja abaixo, na figura da esquerda, o procedimento de insero em uma rvore de ordem 5.

Insero em uma rvore B de ordem 3:


Tente inserir o nodo 10: Cada nodo pode ter no mximo 3 filhos

3 1 2 4 5

6 7 8

Apostila de Algoritmos e Estrutura de Dados III

21

Compresso de Dados
1. Para que comprimir?
Ao contrrio do que possa parecer, comprimir no somente reduzir o tamanho de um arquivo: alm da compresso utilizada em arquivos para reduzir o espao fsico utilizado por eles, h tambm a compresso que utilizada para melhorar a performance em uma trasmisso de dados.

A reduo do espao fsico mais comumente utilizada em bancos de dados que, incorporando a compresso no projeto de seus registros, permite um significativo ganho em termos de ocupao em disco e velocidade de acesso. Exemplos (bancos de dados): Dbase, Interbase, Paradox, Postgress Exemplos (arquivos): Openoffice, Word Como foi mencionado anteriormente, a utilizao mais conhecida da compresso de dados a reduo do espao ocupado por arquivos. De fato, esta aplicao mais comum e mais difundida comercialmente. Afinal, dado um dispositivo restrito de armazenamento que um disquete, e um grande depositrio de arquivos que o disco rgido, evidente a necessidade de muitas vezes realizar-se a reduo do tamanho de arquivos para transport-los ou simplesmente armazen-los. A compresso tambm utilizada para agilizar a transmisso de dados alterando a taxa de transmisso. Se possumos um modem que opera a 9600 bps (bits por segundo), possvel que ele transmita como se estivesse a 14400 bps? Sim! Basta que ele permita a compresso de dados transmitidos, ampliando sua capacidade de transferncia de informao. Na verdade, o modem continuar transmitindo a uma taxa de transmisso de 9600 bps, mas a taxa de transferncia de informao estar ampliada para 14400 bps. A compresso de dados permite, portanto, o aumento na velocidade de transmisso de dados.

2. Tipos de Compresso

1.1. Compresso Lgica A compresso lgica refere-se ao projeto de representao otimizada de dados. Um exemplo clssico o projeto de um banco de dados utilizando seqncias de bits para a representao de campos de dados. No lugar de seqncias de caracteres ou inteiros, utiliza-se bits, reduzindo significativamente o espao de utilizao do banco de dados. Este tipo de compresso possvel de ser efetivada em campos projetados para representar dados constantes, como datas, cdigos e quaisquer outros campos formados por nmeros. A caracterstica lgica da compresso encontra-se no fato dos dados j serem comprimidos no momento do armazenamento, no ocorrendo sua transformao de dados estendidos para comprimidos. Ex.: Representao de 01 de Abril de 2003 : 15 bytes 01 Abr 2002 : 9 bytes 01042002 : 8 bytes Tem como reduzir ainda mais????? A razo da compresso dada por:

tamanho dos dados originais tamanho da cadeia de dados comprimido

2.1. Compresso Fsica A compresso fsica aquela realizada sobre dados existentes, a partir dos quais verificada a repetio de caracteres para efetivar a reduo do nmero de elementos de dados. Existem dois tipos de tcnicas para sinalizar a ocorrncia de caracteres repetidos: 1. um deles indica o caracter (ou conjunto de caracteres) repetido atravs da substituio por um caracter especial; 2. outras tcnicas indicam a freqncia de repetio de caracteres e representam isto atravs de seqncias de bits.

Apostila de Algoritmos e Estrutura de Dados III

22

3. Compresso Orientada a Caracter


As tcnicas de compresso orientadas a caracter no so as mais eficientes ou as mais sofisticadas. Pelo contrrio, em geral elas so utilizadas num primeiro nvel de compresso multinvel, onde os demais nveis podem ser tcnicas estatsticas de compresso. Aqui sero analisados 8 tcnicas de compresso orientada a caracter, de modo a dar uma noo das possveis aplicaes deste tipo de compresso. a) Supresso de Caracteres Nulos ou brancos Nesta tcnica, temos como objetivo comprimir apenas os caracteres nulos ou brancos. Para a compresso, utiliza-se a seguinte seleo de caracteres indicadores: Ce N onde Ce um caracter especial (poderia ser o $, por exemplo) e N o nmero (em binrio) de caracteres brancos repetidos seqencialmente. Ento, por exemplo, uma seqncia do tipo: ... vazio. Exatamente o que... pode ser comprimida como sendo: ... vazio.$8Exatamente o que... o que demonstra uma reduo de 6 bytes no trecho de texto apresentado. Esta tcnica pode ser extendida aos nmeros nulos (zero). Ex.: A seqncia ficaria: #453Joo Silva$2789#4 000053Joo Silva 890000

Outras formas de indicao de compresso podem ser utilizadas, com visto na seo anterior. Como trata-se de uma compresso de brancos, no h a necessidade de explicitao do caracter comprimido. O algoritmo para a tcnica apresentada muito simples: 1. inicializa-se um contador para o clculo do nmero de repeties de brancos; 2. l-se o caracter do arquivo a comprimir; 3. verifica-se se o caracter um branco; 4. se for, incrementa-se o contador e verifica-se se o nmero de caracteres ultrapassou a 255 (limite binrio); se verdadeiro, colocam-se os caracteres indicadores no arquivo comprimido e volta-se ao passo 1, caso contrrio, volta-se ao passo 2; 5. se no for, verifica-se se o contador maior que 2, valendo a pena comprimir; se , colocam-se os caracteres indicadores no arquivo comprimido, e volta-se ao passo 1, se no , copiam-se os caracteres lidos no arquivo comprimido e volta-se ao passo 1. O fluxograma para o algoritmo apresentado mostrado a seguir:

No caso de haver 350 caracteres brancos seguidos, utilizaria-se $255$95 Apostila de Algoritmos e Estrutura de Dados III 23

b) Comprimento de Fileira Tambm chamada de Run-length, esta tcnica utiliza sempre uma combinao de 3 bytes para representar uma compactao. o formato Ce X N onde Ce o caracter especial, X o caracter repetido e N o nmero (binrio) de repeties. No caso de um caracter ser repetido mais do que 255 vezes, basta repetir a combinao Ce X N, onde n ser o nmero de repeties que ainda faltam para comprimir corretamente a cadeia original. Funcionamento do algoritmo: 1. inicializa-se um contador de caracteres, destinado ao controle de cada caracter, buscando a verificao de existncia de repetio; 2. inicializa-se um contador de repeties do caracter procurado;faz-se a leitura do caracter no arquivo a comprimir; 3. incrementa-se o contador de caracteres; 4. se o contador de caracteres for igual a 1, o caracter armazenado e volta-se ao passo 3 para verificao de repetio; 5. verifica-se se o caracter armazenado o que procuramos; se for, incrementa-se o contador de repeties; 6. verifica-se se o contador de repetio maior ou igual a 4; se for menor, gravam-se os caracteres lidos no arquivo comprimido e volta-se ao passo 1; 7. realiza-se a gravao dos caracteres indicadores no arquivo comprimido e volta-se ao passo 1.
contcar = 0 contrep = 1 buffer = '' procurado = caracter L caracter contcar = contcar +1

sim contcar = 1? coloca caracter no buffer

no caracter = procurado? sim contrep = contrep + 1

no sim contrep>= 4 saida = saida + '@' + procurado + chr(contrep)

no saida = saida + '@' + buffer*contrep

buffer = caracter contcar = contrep = 1

Ao terminar a leitura, joga-se o que restou no buffer para a sada

c) Mapeamento de Bit Quando sabida a existncia de mltiplas ocorrncias no consecutivas de determinado caracter no arquivo a comprimir, utiliza-se a compresso por mapeamento de bit. Esta tcnica utiliza-se de um byte no arquivo comprimido para indicar, atravs dos bits, a ocorrncia do caractere repetido. Desta forma, caso desejarmos comprimir todos os caracteres a de um texto, devemos indic-lo no mapa de bits. Cada mapa descreve 8 bytes, um por bit do arquivo manipulado. Portanto, para letra encontrada a cada trecho de 8 bytes, ser assinalada no mapa de bits. Por exemplo: ... abacate ... ser descrito como: ... Mbbcte... onde Mb o mapa de bits correspondente compresso do caracter a . Este mapa composto, para o exemplo, dos bits: onde o primeiro zero indica a presena de um caracter a na primeira posio, valor um em seguida indica um caracter diferente, e assim por diante, at completar o mapa. Convenciona-se, portanto, que o bit 0 indica a presena do caracter a comprimir e o bit 1 a sua ausncia. Apostila de Algoritmos e Estrutura de Dados III 24

O algoritmo para esta tcnica necessita do controle do mapa de bits: 1. inicializa-se o mapa de bits colocando todos os bits em zero; 2. inicializa-se o contador; 3. realiza-se a leitura do caracter no arquivo a comprimir; 4. compara-se o caracter lido com o caracter procurado; se forem o mesmo, ento vai-se para o passo 6; 5. troca-se para 1 o bit da posio atual; 6. incrementa-se o contador; 7. verifica-se se o contador chegou a 8; se verdadeiro, ento grava-se o mapa de bits e os caracteres diferentes do comprimido, e volta-se para o passo 1; seno, volta-se ao passo 3. A seguir apresentado o fluxograma que descreve o algoritmo:

d) Compactao de Meio Byte Este tipo de compactao utilizado quando encontramos uma seqncia de bits em comum nos caracteres de determinado arquivo. Um tipo de repetio de bits de grande ocorrncia a que acontece em caracteres numricos. Por exemplo, se observarmos o conjunto binrio da tabela ASCII para os caracteres numricos, teremos:

ou seja, se isolarmos os primeiros 4 bits de cada byte de caracter numrico, veremos que h uma constncia de valores. Estes valores constantes so um exemplo de objetos de compactao de meio byte. A compactao de meio byte propriamente dita consiste na seguinte seqncia de caracteres indicadores:

onde Ce o caracter especial, N o nmero (binrio) de caracteres comprimidos e Cn a metade do caracter comprimido. Na seqncia de caracteres indicadores apresentada so apresentados 5 caracteres porque este o mnimo para que a compresso seja vlida, uma vez que at 4 caracteres ela necessita um nmero de byte igual ou maior. Observe tambm que o nmero de repeties est ocupando apenas meio byte. Isso significa que ele pode indicar apenas at 16 caracteres, ou seja, este formato permite a compactao de uma seqncia de, no mximo, 16 caracteres. Mas ento surge a pergunta: no h como estender este formato para permitir a compactao de uma seqncia maior de caracteres? A resposta sim, existe a compactao de byte inteiro , onde o nmero N ocupa 1 byte, ao invs de meio. Apostila de Algoritmos e Estrutura de Dados III 25

Neste formato estendido, o restante dos caracteres indicadores permanecem os mesmos, sendo alterado apenas a representao do nmero de caracteres. Com a representao de byte inteiro, a capacidade de compresso aumenta para 256 caracteres, o que permite um ganho expressivo em se tratando de longas seqncias de caracteres. O algoritmo para implementao da compactao de meio byte o seguinte: 1. inicializa-se um contador de caracteres; 2. procede-se a leitura do caracter; 3. verifica-se se o caracter possui a seqncia de bits a comprimir; 4. caso esteja dentro do grupo a comprimir, incrementa-se o contador e volta-se ao passo 2; 5. verifica-se se o contador maior que 4; 6. se no for, gravam-se os caracteres lidos no arquivo comprimido e volta-se ao passo 1, reiniciando o processo; 7. colocam-se os caracteres indicadores no arquivo comprimido e volta-se ao passo 1. O fluxograma para a representao do algoritmo apresentado a seguir.

e) Codificao Diatmica Esta tcnica de compresso permite a representao de um par de caracteres em apenas um caracter especial. Normalmente utilizam-se tabelas com pares de caracteres e sua freqncia de ocorrncia em determinado tipo de arquivo. Obviamente procura-se substituir os caracteres de maior freqncia, associando a cada dupla um caracter especial. Em texto da lngua portuguesa, por exemplo, duplas de ocorrncia freqente so a letra a acentuada com til seguido da letra o (o) e a letra e com acento agudo seguido de um espao em branco ( ). A cada uma dessas seqncia deve-se atribuir um caracter especial para nos permitir a compactao atravs da codificao diatmica. Obviamente, estes so apenas dois exemplos de duplas de caracteres, numa tabela normal para compactao utilizam-se mais de 20 duplas para que seja obtida uma compresso razovel. Para a implementao da codificao diatmica segue-se o seguinte algoritmo: 1. l-se um par de caracteres; 2. verifica-se sua existncia na tabela de pares; 3. se exitente, coloca-se o caracter especial correspondente no arquivo comprimido e volta-se ao passo 1; 4. coloca-se apenas o primeiro caracter no arquivo comprimido; 5. desloca-se o segundo caracter para a primeira posio; 6. l-se o prximo caracter e volta-se ao passo 2. O fluxograma correspondente o seguinte:

Apostila de Algoritmos e Estrutura de Dados III

26

f) Substituio de Padres A substituio de padres semelhante codificao diatmica, pois tambm ocorre a substituio de um conjunto de caracteres por um caracter especial. PALAVRA => Ce A utilizao mais comum para este tipo de compresso a de arquivos de programas de linguagens de programao. Uma vez que as linguagens contm diversas palavras que se repetem freqentemente em programas, utiliza-se esta caracterstica para a sua compresso. Uma variante da substituio de padres para permitir a codificao de um maior nmero de palavras a utilizao de dois caracteres para indicao da ocorrncia de determinada palavra: CN onde C um caracter escolhido para indicar a compresso e N o nmero (binrio) da palavra a substituir. Isso permite a codificao de at 256 palavras reservadas, o que anteriormente era limitado ao nmero de caracteres especiais que poderamos utilizar. Por exemplo, as palavras reservadas begin e end da linguagem Pascal poderiam ser, por exemplo, substitudas pelos cdigos $1 e $2 . As demais palavras reservadas da linguagem tambm poderiam ser codificadas desta maneira, permitindo uma compresso considervel de um arquivo de programa. Como esta tcnica assemelha-se muito da codificao diatmica, deve tomar como base para a programao o algoritmo e o fluxograma apresentados para aquela tcnica. Desta forma no sero apresentados formas distintas de programao.

4. Compresso Estatstica
A idia da compresso estatstica realizar uma representao otimizada de caracteres ou grupos de caracteres. Caracteres de maior freqncia de utilizao so representados por cdigos binrios pequenos, e os de menor freqncia so representados por cdigos proporcionalmente maiores. Neste tipo de compresso portanto, no necessitamos saber qual caracter vai ser comprimido, mas necessrio, porm, ter o conhecimento da probabilidade de ocorrncia de todos os caracteres sujeitos compresso. Caso no seja possvel a tabulao de todos os caracteres sujeitos compresso, utiliza-se uma tcnica adequada para levantamento estatstico dos dados a comprimir, formando tabelas de probabilidades. Para sabermos como foi concebido este tipo de compresso, veremos na seo seguinte a Teoria da Harmonia, a partir da qual teremos uma noo de como se processa a compresso estatstica. 4.1. Teoria da Harmonia Esta Teoria baseia-se no princpio fsico da Entropia. A Entropia a propriedade de distribuio de energia entre os tomos, tendendo ao equilbrio. Sempre que um sistema fsico possui mais ou menos quantidade de energia que outro sistema fsico em contato direto, h troca de energia entre ambos at que atinjam a entropia, ou seja, o equilbrio da quantidade de energia existente nos sistemas. Ao atingir o estado de equilbrio, sabe-se que estes sistemas esto utilizando o mnimo de energia possvel para sua manuteno, e assim se mantero at que outro sistema interaja sobre eles. Aplicada informao, a Teoria da Entropia permite a concepo de uma teoria da Harmonia, ou seja, um ponto de equilbrio onde a informao pode ser representada por uma quantidade mnima de smbolos. Para chegarmos a esta representao ideal, basta que tenhamos a quantidade de smbolos utilizada e a probabilidade de ocorrncia deles. Com base nisso, possvel calcular a quantidade mdia de bits por intervalo de smbolo:

havendo n smbolos, cada qual com uma probabilidade p . A representao de quantidades em binrio dada pela base 2 do logaritmo. Foi utilizado um valor n log n por sua proporcionalidade entre quantidade de informao e tempo (para mais detalhes, veja bibliografia indicada no captulo A). Por outro lado, a frmula apresentada semelhante utilizada para verificao da energia de um sistema fsico, utilizada na Teoria da Entropia. Na prtica, a frmula anteriormente apresentada permite-nos verificar se possvel a otimizao da quantidade de bits utilizados para representao de determinado conjunto de smbolos. Duas representaes podem ser comparadas para a verificao de qual ocupa menos bits em mdia. Isso nos permite concluir que possvel a criao de um mtodo de compactao construdo a partir da probabilidade de ocorrncia de smbolos. Apostila de Algoritmos e Estrutura de Dados III 27

De fato, existem tcnicas que utilizam a anlise da probabilidade para compactao de dados. Estas so chamadas de estatsticas e sero analisadas nas sees seguintes. 4.2. Codificao Huffman Esta tcnica de compresso permite a representao em binrio de caracteres a partir de sua probabilidade de ocorrncia. Esta representao gerada por um sistema de decodificao em rvore binria, o que impede a ambigidade na anlise do cdigo. A ambigidade, neste caso, refere-se a uma decodificao que permite a confuso com outros caracteres. Por exemplo, determinado caracter C1 tem o cdigo binrio 01 e outro caracter C2 tem o cdigo 0100, isto implica que, ao verificarmos a seqncia binria para C2 poderemos estar interpretando como C1, ao serem lidos apenas os bits 01. Por isso, a codificao Huffman utiliza o projeto em rvore binria para projeto dos bits que representam os caracteres, de forma que permitam uma decodificao nica para cada caracter. A codificao Huffman necessita de que cada caracter tenha um valor de probabilidade de ocorrncia. A partir dos caracteres de menor valor, comea a construo da rvore binria. Suponha que aps a anlise estatstica de um arquivo texto a ser compactado verificou-se que 91% dos dados contidos no arquivo sejam os caracteres IHFBDEGCA. Um configurao possvel para a rvore de huffman ento seria:

IHFBD | EGCA I | HFBD I, 15% HF | B H|F H, 1% F, 4% B, 6% 38 % HFB | D D, 12%

91 % E | GCA 53 % GC | A 13 % G|C G, 6% C, 7%

[Tene 95]

E, 25%

28 % A, 15%

A probabilidade do ramo a soma das probabilidades das folhas (GC) 13% = 6% + 7% . Os valores binrios sero membros do cdigo formado. Para a codificao dos prximos caracteres, basta continuarmos a construo da rvore. A probabilidade final da rvore sempre 1,0, uma vez que necessariamente deve-se atingir 100% das ocorrncias de caracteres, permitindo uma codificao total. Uma vez terminada a rvore, basta a formalizao da codificao, que feita com a leitura dos valores binrios, da raiz para as folhas. Os valores binrios lidos sero o cdigo do percurso da raiz at a folha correspondente ao caracter que se deseja o cdigo. A tabela de cdigos fica a seguinte: Tabela dos smbolos e freqncia:
Smbolo A B C D E F G H T Freqncia 15 6 7 12 25 4 6 1 15 Cdigo 111 101 1101 011 10 01001 1100 01000 00

Apostila de Algoritmos e Estrutura de Dados III

28

Desta forma, esto codificados os caracteres atravs da tcnica de Huffman. Observe que o caracter de maior freqncia possui o menor valor. Isso exatamente o objetivo da compresso estatstica, uma vez que permite a substituio do caracter de maior ocorrncia por apenas um bit. Assim acontece com os demais caracteres, em ordem crescente do nmero de bits, conforme a prioridade. Cabe salientar, por fim, que a codificao Huffman manteve a propriedade de permitir a decodificao direta, no permitindo que os bits da codificao de um caracter confundisse com a de outro. 4.3. Codificao Shannon-Fano A forma desta tcnica tem muitas semelhanas com a de Huffman. Necessita-se de uma tabela com a probabilidade de ocorrncia de cada caracter, e de um procedimento para a codificao em binrio. Por outro lado, o procedimento para a codificao, diferentemente de Huffman, baseia-se na diviso de conjuntos de probabilidades para a obteno do cdigo binrio. Para a codificao, devemos ter os caracteres com suas probabilidades de ocorrncia:

O passo seguinte ordenar colocando os caracteres de maior probabilidade no topo da tabela, at o menor, na base:

Uma vez feito isso, divide-se a tabela em dois grupos cuja soma de probabilidades seja igual ou semelhante. No caso da tabela acima, sero obtidos dois grupos, um composto pelo caracter C1 e outro pelos demais. O primeiro grupo recebe como primeiro valor de cdigo o binrio 0 e o segundo recebe 1:

Como para o primeiro grupo no h ambigidade em termos apenas um bit, vamos resolver o problema do segundo grupo. Para isso, repetimos o procedimento anterior, dividindo em dois subgrupos de probabilidades equivalentes. O caracter C2 forma o primeiro subgrupo e os demais formam o segundo. Mais uma vez vamos colocar 0 para distinguir o primeiro e 1 para o segundo:

Finalmente, para resoluo da ltima duplicidade, repete-se o processo, inserindo o binrio 0 na seqncia do cdigo de C1 e 1 para C3:

Apostila de Algoritmos e Estrutura de Dados III

29

Teoria dos Grafos


A teoria dos grafos estuda problemas computacionais que envolvem objetos conhecidos como grafos Os problemas tornaram-se clebres porque ocorrem em diversas reas da computao, da engenharia, e em muitas aplicaes industriais. Parte do material abaixo um curso de algoritmos para grafos baseado no livro Algorithms in C: Graph Algorithms de R. Sedgewick.

Conceitos bsicos
Um digrafo (digraph = directed graph) composto por um conjunto de nodos e um conjunto de arestas, tal que: - vrtice (n, ponto): representa uma entidade, como uma pessoa, uma fruta ou um pedao de terra. - Arestas ou arcos (linha): a relao que liga 2 nodos, tal como irmo que liga 2 pessoas. Notao: G (n,a): onde G o nome do grafo, n o nmero de nodos e n o nmero de arestas. Exemplo: G(4,7) um grafo com 4 nodos e 7 arestas:

3 1 4 2

Grau = 3

Uma boa maneira de especificar um digrafo exibir seu conjunto de arcos. O Conjunto de arcos do digrafo abaixo :

b a c
a-a, a-b, a-d, a-c, c-d, d-f, f-c, f-g. Nota-se que a-b indica um arco do sentido de a at b.

d f

Digrafo simtrico O grafo simtrico quando se cada um dos arcos anti-paralelo a outro arco. Por exemplo, se existir o arco 0-5, deve existir o arco 5-0. Grafo So os tipos especiais de digrafos que so no orientado. Para simplificao, utilizaremos a partir de agora a notao grafo para ambos (grafos e digrafos). Grau de um vrtice O grau de entrada e de sada de um vrtice em um grafo determinado pela quantidade de arestas que incidem sobre ele e a quantidade de arcos que saem dele, respectivamente. Exemplo: os nodos so cidades e os arcos contm a distncia entre duas cidades:

15 D
3

12

Apostila de Algoritmos e Estrutura de Dados III

F
30

Representaes computacionais de grafos


Considerando o grafo abaixo:

2
b

1
d
As seguintes representaes so possveis:

4 3

g
f

a) Matriz de adjacncia:
1 1 2 3 4 5 6 2 3 4 5 6

Estrutura
Um digrafo ser representado por uma struct graph que contm o nmero de vrtices, o nmero de arcos e a matriz de adjacncia do digrafo. /* A estrutura digraph representa um digrafo. O campo adj um ponteiro para a matriz de adjacncia do digrafo. O campo V contm o nmero de vrtices e o campo A contm o nmero de arcos do digrafo.*/
struct int int int }; graph { V; A; **adj;

/* Um objeto do tipo Graph contm o endereo de um graph.*/ typedef struct graph *Graph; /* Pode-se utilizar o nome digraph ou graph conforme a preferncia*/ #define digraph graph; #define Digraph Graph;

b) Matriz de incidncia:
a 1 2 3 4 5 6 b c d e f 0 g 0 h 0

c) Lista de adjacncia

-1 1

-1 -1 0

A[i,j]=

Apostila de Algoritmos e Estrutura de Dados III

31

Exemplo de Aplicao de grafos


Kaliningrad, antigamente Knigsberg uma cidade do oeste da Rssia, junto ao Rio Pregel. A capital de Kaliningrad, Oblast, o um grande centro industrial e comercial, ligado por um canal com Baltiysk, um porto no Mar Bltico. O matemtico Leonardo euler (1707-1786) deu incio ao estudo de grafos ao solucionar o problema das pontes de Konisberg, ao provar que no era possvel atravessar todas as pontes usando um nico caminho.

O problema das "Pontes de Knigsberg ".


"O rio Pregel tem duas ilhas. Estas esto unidas por uma ponte. Uma ilha tem uma ponte que a une a ambas as margens; a outra tem duas pontes para cada margem. Podem os cidados de Conisberga atravessar todas as sete pontes num s passeio contnuo? " Ele fundou sem saber a base da teoria dos grafos

Resposta:
Se procuramos um caminho contnuo, sem passar duas vezes pela mesma ponte, a resposta negativa. Vejamos uma justificao simples: vamos substituir o desenho por um correspondente diagrama, ou seja, um modelo do nosso problema; fazendo corresponder a cada massa de terra um ponto e a cada ponte uma linha, ligando de seguida os pontos apropriados. A chave do problema reside no fato de cada ponto ou um ponto de partida, de chegada ou de passagem. Se um ponto tem um nmero mpar de caminhos ter de ser um ponto de partida ou de chegada. Para fazermos um caminho contnuo temos de passar por todos os pontos, pelo que os que no so de partida ou de chegada tm de possuir um nmero par de caminhos, pois se chegamos temos de partir. No problema colocado temos quatro pontos com um nmero mpar de caminhos, quer isto dizer, que temos trs pontos que no podem ser de passagem. Logo no possvel efetuar o caminho contnuo proposto. De um modo geral e intuitivamente, conclumos que:

os habitantes s podiam efectuar um caminho contnuo se todos os pontos tivessem um nmero par de caminhos; no tendo todos um nmero par de caminhos, apenas dois podiam ter um nmero mpar, um seria o ponto de partida o outro o de chegada.

Grafos Eulerianos
O estudo de Leunard Euler deu origem trajetria euleriana: um caminho completo, que passe por todas as arestas de um grafo, sem retraar nenhuma aresta. Exemplos

c a

d b e

c a

d f b

Apostila de Algoritmos e Estrutura de Dados III

32

Grafos Hamiltoniano
O matemtico irlands Willian Powan Hamilton, criou uma trajetria um pouco diferente da trajetria euleriana. Deve-se aqui passar por todos os vrtices do grafo sem repetir nenhum vrtice, comeando e terminando no mesmo vrtice. Um grafo euleriano apresentado abaixo:

Um clssico problema hamiltoniano o problema do caixeiro-viajante. Nesse problema, um caixeiro viajante deve visitar vrias cidades e retornar ao ponto de partida. Como podem haver vrios ciclos Hamiltonianos, o objetivo a pode ser encontrar o ciclo de menor peso total. Esse um algoritmo denominado NP Completo. No existe algoritmo eficiente para isso. Para 9 cidades, por exemplo, seriam necessrias 8! combinaes (o que nos daria 40320 caminhos). Veja o exemplo abaixo com 5 cidades:

d c a b d E______ f H______ c a c g a e b d f E______ H______ c d a b d E______ H______ b c d d

Exerccios. Indique para os grafos abaixo se existe pelo menos 1 caminho Euleriano e 1 hamiltoniano para cada um:

c e a

d b

E______ H______ b d a d E______ H______

Algoritmos para grafos + conhecidos e a sua aplicao


a) Dijkstra
Um dos algoritmos mais conhecidos de grafos o dijkstra. o algoritmo mais eficiente quando se deseja calcular o melhor caminho para seguir em um grafo ponderado. O funcionamento o seguinte. Escolhe-se a origem (um vrtice qualquer do grafo que representaria no caso uma cidade) e a partir da, o algoritmo retorna a menor distncia desta origem para cada um de todos os outros vrtices existentes. Ou seja, se a cidade origem o nodo 0, por exemplo, o algoritmo monta uma rvore mnima com o menor caminho possvel para cada um dos outros nodos. Vejamos o exemplo a seguir, considerando o mapa abaixo:
6 0 0 3 3 5 5 4 1 4 2 1 1 0 11 1 5 0 5 1 4 3 4 2 3 2 5 41 29 45 38 29 21 36 32 32 50 51

Obs.: A explicao do Dikstra ser feita em sala de aula, no quadro-negro, apresentando os trs vetores: cst, from e parnt

Apostila de Algoritmos e Estrutura de Dados III

33

Aplicao do Dijkstra - Maratona de Programao da SBC ACM ICPC 2006 pgina 6

Problema C
Pases em Guerra
Nome do arquivo fonte: paises.c, paises.cpp, paises.java
No ano 2050, aps diversas tentativas da ONU de manter a paz no mundo, explode a terceira guerra mundial. Segredos industriais, comerciais e militares obrigaram todos os pases a utilizar servios de espionagem extremamente sofisticados, de forma que em cada cidade do mundo h ao menos um espio de cada pas. Esses espies precisam se comunicar com outros espies, com informantes e mesmo com as suas centrais durante as suas aes. Infelizmente no existe uma forma segura de um espio se comunicar em um perodo de guerra, ento as mensagens so sempre enviadas em cdigo para que somente o destinatrio consiga ler a mensagem e entender o seu significado. Os espies utilizam o nico servio que funciona no perodo de guerra, os correios. Cada cidade possui uma agncia postal onde as cartas so enviadas. As cartas podem ser enviadas diretamente ao seu destino ou a outras agncias postais, at que a carta chegue agncia postal da cidade de destino, se isso for possvel. Uma agncia postal na cidade A pode enviar diretamente uma carta impressa para a agncia postal da cidade B se houver um acordo de envio de cartas, que determina o tempo, em horas, que uma carta leva para chegar da cidade A cidade B (e no necessariamente o contrrio). Se no houver um acordo entre as agncias A e B, a agncia A pode tentar enviar a carta a quantas agncias for necessrio para que a carta chegue ao seu destino, se isso for possvel. Algumas agncias so interligadas por meios eletrnicos de comunicao, como satlites e fibras pticas. Antes da guerra, essas ligaes atingiam todas as agncias, fazendo com que uma carta fosse enviada de forma instantnea, mas durante o perodo de hostilidades cada pas passou a controlar a comunicao eletrnica e uma agncia somente pode enviar uma carta outra agncia por meio eletrnico (ou seja, instantaneamente) se ela estiver no mesmo pas. Duas agncias, A e B, esto no mesmo pas se houver uma forma de uma carta impressa enviada de uma das agncias ser entregue na outra agncia. O servio de espionagem do seu pas conseguiu obter o contedo de todos os acordos de envios de mensagens existentes no mundo e deseja descobrir o tempo mnimo para se enviar uma carta entre diversos pares de cidades. Voc seria capaz de ajud-lo?

Entrada
A entrada contm vrios casos de teste. A primeira linha de cada caso de teste contm dois inteiros separados por um espao, N (1 N 500) e E (0 E N2), indicando o nmero de cidades (numeradas de 1 a N) e de acordos de envio de mensagens, respectivamente. Seguem-se, ento, E linhas, cada uma com trs inteiros separados por espaos, X, Y e H (1 X, Y N, 1 H 1000), indicando que existe um acordo para enviar uma carta impressa da cidade X cidade Y , e que tal carta ser entregue em H horas. Em seguida, haver uma linha com um inteiro K (0 K 100), o nmero de consultas. Finalmente, viro K linhas, cada uma representando uma consulta e contendo dois inteiros separados por um espao, O e D (1 O,D N). Voc deve determinar o tempo mnimo para se enviar uma carta da cidade O cidade D. O final da entrada indicado por N = 0. A entrada deve ser lida da entrada padro.

Sada
Para cada caso de teste da entrada seu programa deve produzir K linhas na sada. A I-sima linha deve conter um inteiro M, o tempo mnimo, em horas, para se enviar uma carta na I-sima consulta. Se no houver meio de comunicaco entre as cidades da consulta, voc deve imprimir Nao e possivel entregar a carta (sem acentos). Imprima uma linha em branco aps cada caso de teste. A sada deve ser escrita na sada padro.

Apostila de Algoritmos e Estrutura de Dados III

34

Exemplo de entrada
4 1 2 3 4 2 5 1 1 1 4 4 3 1 2 3 3 1 3 3 0 5 2 1 4 3 3 5 10 8 7 6

Sada para o exemplo de entrada

0 6 6 0 Nao e possivel entregar a carta 10 Nao e possivel entregar a carta 0

2 3 4 3 1 3 2 10 3 1 2 1 3 1 2 0

Resoluo a) Interpretao
Como muitas vezes j foi falado em sala de aula, a resoluo de um problema j comea na sua correta interpretao. Pois bem, 90% de quem ler o enunciado far uma interpretao errada do problema. Existe uma frase no meio do texto que diz o seguinte: Duas agncias, A e B, esto no mesmo pas se houver uma forma de uma carta impressa enviada de uma das agncias ser entregue na outra agncia. Pois bem. Desta forma, independendo da distncia, se houver uma ligao de ida e volta entre duas cidades, isso significa que elas esto no mesmo pas, e portanto, o custo de tempo de entrega sempre ser 0 (zero), pois ela ser entregue instantaneamente por meio eletrnico.

b) Entrada
Feita a interpretao correta do exerccio, o que no uma tarefa muito fcil passamos para o prximo passo, que analisar as entradas do problema A entrada contm vrios casos de teste. A primeira linha de cada caso de teste contm dois inteiros separados por um espao, N (1 N 500) e E (0 E N2), indicando o nmero de cidades (numeradas de 1 a N) e de acordos de envio de mensagens, respectivamente. Bem, neste caso temos cidades (N) e acordos (E) que no algoritmo chamaremos de cidades e acordos para facilitar a compreeno, sendo que os seguintes valores so possveis para cada uma das variveis: int cidades ( 1 at 500), acordos ( 0 at 250.000)

Exemplo de entrada
4 5 Seguem-se, ento, E linhas, cada uma com trs inteiros separados por espaos, X, Y e H (1 X, Y N, 1 H 1000), indicando que existe um acordo para enviar uma carta impressa da cidade X cidade Y , e que tal carta ser entregue em H horas. Bem, ento considerando o nmero de acordos (5 para o exemplo), para cada um deles teremos a origem (X), o destino (Y) e tempo (H). int origem ( mnimo 1 ), destino (<=500), tempo (entre 1 e 1000) Apostila de Algoritmos e Estrutura de Dados III 35

Exemplo de entrada
4 1 2 3 4 2 5 2 1 4 3 3 5 10 8 7 6

5 10 8 2 Obs.: conforme explicado anteriormente, as cidades 1 e 2 esto


em 1 mesmo pas, o mesmo valendo para as cidades 3 e 4.

3 7

Em seguida, haver uma linha com um inteiro K (0 K 100), o nmero de consultas. Finalmente, viro K linhas, cada uma representando uma consulta e contendo dois inteiros separados por um espao, O e D (1 O,D N). Voc deve determinar o tempo mnimo para se enviar uma carta da cidade O cidade D. int consultas (de 0 a 100) //Neste caso, pode-se utilizar a mesma varivel origem e destino, para O e D respectivamente, uma vez que aps a entrada anterior, estas variveis esto disponveis

Exemplo de entrada
4 1 2 3 4 2 5 1 1 1 4 4 5 2 1 4 3 3 2 3 4 3 1 5 10 8 7 6

1 0 Sada.: neste caso, convorme o mapa acima, fica fcil definir as sadas:
0 6 6 0 Nao (a cidade 1 e a cidade 2 esto no mesmo pas) (existem 6 horas de tempo da cidade 2 p/ a 3) (existem 6 horas de tempo da cidade 2 p/ a 3) (a cidade 4 e a cidade 3 esto no mesmo pas) e possivel entregar a carta

0 2
6

0 4 0

Programa
a) Declarao do Grafo
A estrutura digraph representa um digrafo. O campo adj um ponteiro para a matriz de adjacncia do digrafo. O campo Vertices contm o nmero de Vrtices e o campo A contm o nmero de arcos do digrafo. */ struct digraph { int V; int A; int adj[501][501]; }; typedef struct digraph *Digraph;

Algumas definies utilizadas:


#define #define #define #define #define #define maxV 501 maxCST 999999 INFINITO 999999 Vertices int graph digraph Graph Digraph

>> Para facilitar, optou-se em no utilizar as posies 0 da matriz adj, por isso a definio com 501 espaos, ao invs de 500

b) Variveis declaradas no programa principal

int main(void){ Digraph D; D= new (struct digraph); int i,j,cidades,acordos,consultas,Origem,Destino,Tempo; Vertices parnt[501]; // Vetor utilizado no algoritmo de Dijkstra double cst[501]; // Vetor utilizado no algoritmo de Dijkstra // O vetor fr[501] from declarado dentro da funo Dijkstra

c) Aps ler as cidades e acordos deve-se inicializar a estrutura digrap:


cin >> cidades; cin >> acordos; while (cidades){ // Inicializao da estrutura digraph, colocando INFINITO // para todos as posies da matriz de adjacncia (adj) for (i=0;i<=cidades;i++) for (j=0;j<=cidades;j++) D->adj[i][j]=INFINITO;

Apostila de Algoritmos e Estrutura de Dados III

36

d) Colocao das distncias na matriz de adjacncia


// Colocao de todas as distncias entre as cidades (tempos) // para todos as posies da matriz de adjacncia (adj) // IMPORTANTE: Se existir rota de ida e de volta entre 2 // agncias, deve-se considerar que elas esto no mesmo pas, e // a distncia entre elas neste caso deve ser = ZERO (*%) for (i=0; i<acordos; i++){ cin >> Origem; cin >> Destino; cin >> Tempo; if (D->adj[Destino][Origem]!=INFINITO) { D->adj[Origem][Destino]=0; //*% D->adj[Destino][Origem]=0; //*% } else D->adj[Origem][Destino]=Tempo; } D->V=cidades+1; // para vrtices irem de 1 at 500, e no de 0 at 499 D->A=acordos;

e) Por fim, as consultas das horas que levaria para chegar a carta de uma cidade outra, e a impresso de uma linha em branco no final
cin >> consultas; for (int i=0; i< consultas; i++){ cin >> Origem; cin >> Destino; Dijkstra (D,Origem,parnt,cst,Destino); } cout << endl;

f) algoritmo de dijkstra (adaptado no final para mostrar as mensagens que o programa exige

void Dijkstra (Digraph G, Vertices s, Vertices parnt[], double cst[], Vertices Destino) { Vertices w, w0, fr[maxV]; for (w = 0; w < G->V; w++) { parnt[w] = -1; cst[w] = maxCST; } fr[s] = s; cst[s] = 0.0; while (1) { double mincst = maxCST; for (w = 0; w < G->V; w++) { if (parnt[w] == -1 && mincst > cst[w]) { mincst = cst[w0=w]; } } if (mincst == maxCST) break; parnt[w0] = fr[w0]; for (w = 0; w < G->V; w++) if (cst[w] > cst[w0] + G->adj[w0][w]) { cst[w] = cst[w0] + G->adj[w0][w]; fr[w] = w0; }

// Adaptao para este problema em especfico if (cst[Destino] < INFINITO) cout << cst[Destino]; else cout << "Nao e possivel entregar a carta" ; cout << endl;

Exerccio: implemente o programa acima e com a entrada real de teste (paises.in), confira quanto tempo ir demorar para executar todos os casos de teste.

Apostila de Algoritmos e Estrutura de Dados III

37

b) Floyd
Igualmente ao dijkstra, esse algoritmo faz uma matriz de custo do grafo. Ou seja, ele verifica a distncia entre cada par de vrtices. Se existir uma aresta, o valor que ele coloca naquela posio da matriz o custo da aresta. Se no existir uma aresta entre o par de vrtice, ele coloca o valor . Em seguida, ele verifica se existe um caminho de menor custo entre cada par de vrtices, ao passar por um vrtice intermedirio. Ou seja, suponha um grafo com 5 vrtices. De um modo geral, aps montar a matriz de distncias, ele far 5 iteraes:
1. Iterao: descobrir se h caminhos que ficam menores ao passar pelo vrtice 1 2. Iterao: descobrir se h caminhos que ficam menores ao passar pelo vrtice 2 3. Iterao: descobrir se h caminhos que ficam menores ao passar pelo vrtice 3 4. Iterao: descobrir se h caminhos que ficam menores ao passar pelo vrtice 4 5. Iterao: descobrir se h caminhos que ficam menores ao passar pelo

Grafo exemplo para entrada


4

1
8
3 3

2
20

a) Matriz de adjacncia: 3
1 2 3 4 5 6 1 2 3 4 5 6

4
3

5
2

void digraph::floyd (void) { // Para caso real substitua o 6 por v (vrtices) for (int k=1; k <= 6; k++) { // k <= D->V for (int i=1; i <= 6; i++) { for (int j=1; j <= 6; j++){ if ( (D->adj[j][k]+D->adj[k][i] < D->adj[j][i]) ) { D->adj[j][i]=D->adj[j][k]+D->adj[k][i]; }// j,k + k,i < j,i j,k + k,i < j,i j,k + k,i < j,i j,k + k,i } // 1,1 + 1,1 < 1,1 1,1 + 1,2 < 1,2 1,1 + 1,3 < 1,3 1,1 + 1,4 } // 2,1 + 1,1 < 2,1-> 2,1 + 1,2 < 2,2-> 2,1 + 1,3 < 2,3-> 2,1 + 1,4 } // 3,1 + 1,1 < 3,1 3,1 + 1,2 < 3,2 3,1 + 1,3 < 3,3 3,1 + 1,4 } // 4,1 + 1,1 < 4,1 4,1 + 1,2 < 4,2 4,1 + 1,3 < 4,3 4,1 + 1,4 // 5,1 + 1,1 < 5,1 5,1 + 1,2 < 5,2 5,1 + 1,3 < 5,3 5,1 + 1,4 // 6,1 + 1,1 < 6,1 6,1 + 1,2 < 6,2 6,1 + 1,3 < 6,3 6,1 + 1,4 // // // // // // // // // // // // 1,2 2,2 3,2 4,2 5,2 6,2 1,3 2,3 3,3 4,3 5,3 6,3 + + + + + + + + + + + + 2,1 2,1 2,1 2,1 2,1 2,1 3,1 3,1 3,1 3,1 3,1 3,1 < < < < < < < < < < < < 1,1 2,1-> 3,1 4,1 5,1 6,1 1,1 2,1-> 3,1 4,1 5,1 6,1 1,2 2,2 3,2 4,2 5,2 6,2 1,3 2,3 3,3 4,3 5,3 6,3 + + + + + + + + + + + + 2,2 2,2 2,2 2,2 2,2 2,2 3,2 3,2 3,2 3,2 3,2 3,2 < < < < < < < < < < < < 1,2 2,2-> 3,2 4,2 5,2 6,2 1,2 2,2-> 3,2 4,2 5,2 6,2 1,2 2,2 3,2 4,2 5,2 6,2 1,3 2,3 3,3 4,3 5,3 6,3 + + + + + + + + + + + + 2,3 2,3 2,3 2,3 2,3 2,3 3,3 3,3 3,3 3,3 3,3 3,3 < < < < < < < < < < < < 1,3 2,3-> 3,3 4,3 5,3 6,3 1,3 2,3-> 3,3 4,3 5,3 6,3 1,2 2,2 3,2 4,2 5,2 6,2 1,3 2,3 3,3 4,3 5,3 6,3 + + + + + + + + + + + + 2,4 2,4 2,4 2,4 2,4 2,4 3,4 3,4 3,4 3,4 3,4 3,4

< < < < < < < < < < < < < < < < < < <

j,i 1,4 2,4 3,4 4,4 5,4 6,4 1,4 2,4 3,4 4,4 5,4 6,4 1,4 2,4 3,4 4,4 5,4 6,4

... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...

Apostila de Algoritmos e Estrutura de Dados III

38

// // // // // // // // // // // // // // // // // //

1,4 2,4 3,4 4,4 5,4 6,4 1,5 2,5 3,5 4,5 5,5 6,5 1,6 2,6 3,6 4,6 5,6 6,6

+ + + + + + + + + + + + + + + + + +

4,1 4,1 4,1 4,1 4,1 4,1 5,1 5,1 5,1 5,1 5,1 5,1 6,1 6,1 6,1 6,1 6,1 6,1

< < < < < < < < < < < < < < < < < <

1,1 2,1-> 3,1 4,1 5,1 6,1 1,1 2,1-> 3,1 4,1 5,1 6,1 1,1 2,1-> 3,1 4,1 5,1 6,1

1,4 2,4 3,4 4,4 5,4 6,4 1,5 2,5 3,5 4,5 5,5 6,5 1,6 2,6 3,6 4,6 5,6 6,6

+ + + + + + + + + + + + + + + + + +

4,2 4,2 4,2 4,2 4,2 4,2 5,2 5,2 5,2 5,2 5,2 5,2 6,2 6,2 6,2 6,2 6,2 6,2

< < < < < < < < < < < < < < < < < <

1,2 2,2-> 3,2 4,2 5,2 6,2 1,2 2,2-> 3,2 4,2 5,2 6,2 1,2 2,2-> 3,2 4,2 5,2 6,2

1,4 2,4 3,4 4,4 5,4 6,3 1,5 2,5 3,5 4,5 5,5 6,5 1,6 2,6 3,6 4,6 5,6 6,6

+ + + + + + + + + + + + + + + + + +

4,3 4,3 4,3 4,3 4,3 4,3 5,3 5,3 5,3 5,3 5,3 5,3 6,3 6,3 6,3 6,3 6,3 6,3

< < < < < < < < < < < < < < < < < <

1,3 2,3-> 3,3 4,3 5,3 6,3 1,3 2,3-> 3,3 4,3 5,3 6,3 1,3 2,3-> 3,3 4,3 5,3 6,3

1,4 2,4 3,4 4,4 5,4 6,4 1,5 2,5 3,5 4,5 5,5 6,5 1,6 2,6 3,6 4,6 5,6 6,6

+ + + + + + + + + + + + + + + + + +

4,4 4,4 4,4 4,4 4,4 4,4 5,4 5,4 5,4 5,4 5,4 5,4 6,4 6,4 6,4 6,4 6,4 6,4

< < < < < < < < < < < < < < < < < <

1,4 2,4 3,4 4,4 5,4 6,4 1,4 2,4 3,4 4,4 5,4 6,4 1,4 2,4 3,4 4,4 5,4 6,4

... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...

Exerccio: com base na resoluo do problema paises.cpp, implemente a resoluo de duas outras maneiras: a) modifique o fonte original que utiliza o dijkstra utilizando classes ao invs de structs (baseie-se no fonte abaixo) b) implemente a mesma resoluo utilizando agora o floyd e compare o tempo de execuo dos 2.
// Aplicao do algoritmo de Floyd para encontrar todos os melhores caminhos #include <iostream> #include <iomanip> #define INFINITO 999999 #define Vertex int #define graph digraph using namespace std; /* A estrutura digraph representa um digrafo. adj a matriz de adjacncia do digrafo. O campo Vertices contm o nm. de Vrtices e o campo A contm o nm. de arcos do digrafo */ class digraph { public: int V; int A; int adj[501][501]; void floyd (void); }; digraph *D; /* Um objeto do tipo Digraph contm o endereo de um digraph. */

void digraph::floyd (void) { // Para caso real substitua o 6 por v (vrtices) ... int main(void){ D= new (class digraph); int i,j,cidades,acordos,consultas,Origem,Destino,Tempo; cin >> cidades; ...

c) Bellman-Ford
O Algoritmo de Bellman-Ford, igualmente ao Dijkstra, um algoritmo de busca de caminhos mnimos em um digrafo ponderado, ou seja, cujas arestas tm peso, inclusive negativo. O Algoritmo de Dijkstra resolve o mesmo problema em um tempo muito menor, porm exige que todas as arestas tenham pesos positivos. Portanto, o algoritmo de Bellman-Ford normalmente usado apenas quando existem arestas de peso negativo.

Apostila de Algoritmos e Estrutura de Dados III

39

// Aplicao do algoritmo de Bellman-Ford no problema dos pases em guerra #include <iostream> #include <cstdio> using namespace std; #define INFINITY 99999999 typedef struct { int source; int dest; int weight; } Edge; void BellmanFord(Edge edges[], int edgecount, int nodecount, int source, int dest){ int i,j; int distance[501]; for (i = 0; i < nodecount; i++) { if (i == source) distance[i] = 0; else distance[i] = INFINITY; } for (i = 0; i < nodecount; i++) { for (j = 0; j < edgecount; j++) { if (distance[edges[j].dest] > distance[edges[j].source] + edges[j].weight){ distance[edges[j].dest] = distance[edges[j].source] + edges[j].weight; } } } if (distance[dest] < 100000) cout << distance[dest]; else cout << "Nao e possivel entregar a carta"; cout << endl; } int main (void){ Edge Arestas[25000]; int cidades, acordos,consultas, org , dest; while (1){ cin >> cidades; cin >> acordos; if (cidades==0) break; for (int i=0; i < acordos; i++){ cin >> Arestas[i].source; cin >> Arestas[i].dest; cin >> Arestas[i].weight; } for (int i=0; i < acordos; i++){ for (int j=i; j < acordos; j++){ if ((Arestas[j].source==Arestas[i].dest)&&(Arestas[j].dest==Arestas[i].source)) Arestas[i].weight=Arestas[j].weight=0; } } cin >> consultas; for (int i=0; i < consultas; i++){ cin >> org; cin >> dest; BellmanFord(Arestas,acordos,cidades+1,org,dest); } cout << endl;

} return(0);

Exerccio: Implemente o Algoritmo de Bellman-Ford, e compare a performance com o Floyd e Dijkstra comparando o tempo necessrio para rodar a entrada padro paises.in.

Apostila de Algoritmos e Estrutura de Dados III

40

Você também pode gostar