apostila estrutura de dados

Upload: jorge-azevedo

Post on 14-Jul-2015

1.685 views

Category:

Documents


0 download

TRANSCRIPT

Prof. Lzaro Eduardo da Silva

Apostila de Estrutura de Dados 2

Bacharelado em Cincia da Computao

20093 Perodo

Estrutura de Dados 2 - Lzaro Eduardo da Silva

Sumrio1 2 INTRODUO ............................................................................................................... 3 TIPO APONTADOR (PONTEIRO)............................................................................... 3 2.1 PONTEIROS................................................................................................................ 4 2.1.1 Declarao: ........................................................................................................ 4 2.1.2 Inicializao: ...................................................................................................... 4 2.1.3 Criao de uma varivel dinmica: ................................................................... 4 2.1.4 Destruio de uma varivel dinmica: .............................................................. 5 2.1.5 Referncia a uma varivel dinmica:................................................................. 5 PILHAS E FILAS ........................................................................................................... 6 3.1 PILHA ........................................................................................................................ 6 3.1.1 Implementao de Pilha usando Alocao Dinmica de Memria ................... 6 3.2 FILA ......................................................................................................................... 11 3.2.1 Implementao de Fila usando Alocao Dinmica de Memria ................... 11 LISTAS LINEARES ..................................................................................................... 14 4.1 LISTAS LINEARES POR ENCADEAMENTO ............................................................... 14 4.1.1 Lista Linear Encadeada usando Vetor: ............................................................ 15 4.1.2 Lista Encadeada usando Alocao Dinmica de Memria ............................. 21 RECURSIVIDADE ....................................................................................................... 27 5.1 O PROBLEMA DAS TORRES DE HANOI .................................................................... 28 RVORE ....................................................................................................................... 31 6.1 RVORE BINRIA ................................................................................................... 32 6.1.1 Caminhamento em rvore Binria ................................................................... 32 6.1.2 Construo de rvore Binria: ........................................................................ 33 6.1.3 Insero, Remoo e Consulta ordenada em rvore Binria: ........................ 34 MTODOS DE CLASSIFICAO ............................................................................. 42 7.1 CLASSIFICAO POR TROCA .................................................................................. 42 7.2 CLASSIFICAO POR SELEO .............................................................................. 44 7.3 CLASSIFICAO POR INSERO ............................................................................. 46 BIBLIOGRAFIA........................................................................................................... 49

3

4

5 6

7

8

pgina 2

Estrutura de Dados 2 - Lzaro Eduardo da Silva

1

Introduo

A automatizao de tarefas um aspecto marcante da sociedade moderna e na cincia da computao houve um processo de desenvolvimento simultneo e interativo de mquinas (hardware) e dos elementos que gerenciam a execuo automtica (software) de uma tarefa. Nesta grande evoluo do mundo computacional, um fator de relevante importncia a forma de armazenar as informaes, j que, informtica a cincia da informao. Ento de nada adiantaria o grande desenvolvimento do hardware e do software, se a forma de armazenamento e tratamento da informao no acompanhasse esse desenvolvimento. Por isso a importncia das estruturas de dados, que nada mais so, que formas otimizadas de armazenamento e tratamento das informaes eletronicamente. As estruturas de dados, na sua maioria dos casos, foram espelhadas em formas naturais de armazenamento do nosso dia a dia, ou seja, nada mais so que a transformao de uma forma de armazenamento j conhecida e utilizada no nosso mundo para o mundo computacional. Por isso, cada tipo de estrutura de dados possui vantagens e desvantagens e cada uma delas tem sua rea de atuao tima. Um algoritmo um processo sistemtico para resoluo de um problema. O desenvolvimento de algoritmos particularmente importante para problemas a serem solucionados em um computador, pela prpria natureza do instrumento utilizado. Um algoritmo computa uma sada, o resultado do problema, a partir de uma entrada, as informaes inicialmente conhecidas e permitem encontrar a soluo do problema. Durante o processo de computao, o algoritmo manipula dados, gerados a partir de sua entrada. Quando os dados so manipulados de uma forma homognea, constituem um tipo abstrato de dados. Este composto por um modelo matemtico acompanhado por um conjunto de operaes definido sobre este modelo. Um algoritmo projetado em termos de tipos abstratos de dados. Para implement-los numa linguagem de programao, necessrio encontrar uma forma de represent-los nessa linguagem, utilizando-se tipos e operaes suportadas pelo computador. Na representao do modelo matemtico emprega-se uma estrutura de dados. As estruturas diferem uma das outras pela disposio ou manipulao de seus dados. A disposio dos dados em uma estrutura obedece a condies preestabelecidas e caracteriza a estrutura. At aqui, as estruturas apresentadas eram estticas (vetores e matrizes). Agora novas estruturas de dados sero apresentadas, sendo que, todas elas sero estruturas de dados dinmicas, ou seja, crescem e diminuem de acordo com a necessidade, veremos que, para isso, sero necessrias vrias rotinas que controlam esta dinamicidade das estruturas.

2

Tipo Apontador (Ponteiro)

Um das caractersticas mais marcantes de linguagens estruturadas permitir a criao e destruio de variveis durante a execuo do programa. O uso dessas variveis possibilita a implementao das estruturas de dados dinmicas. Essas variveis criadas e destrudas durante a execuo do programa so chamadas variveis dinmicas. Uma varivel dinmica no declarada na parte de declarao de variveis porque esta ainda no existe antes do seu tempo de execuo, ela no possui sequer um nome, ficando a cargo dos ponteiros desempenharem esta funo de nome. Uma varivel dinmica sempre referenciada indiretamente por um apontador, ou seja, para cada varivel dinmica criada deve existir um apontador, que literalmente aponta para ela, permitindo a sua manipulao. Os apontadores so declarados como as demais variveis, seguindo a sintaxe da linguagem de programao utilizada. Eles so variveis que armazenam o endereo de memria de outras variveis, funcionando assim, como meio de referenciar uma varivel dinmica, permitindo o acesso a essa varivel. Outra caracterstica dos apontadores que na sua declarao deve ser indicado qual o tipo de varivel este ir armazenar o endereo. A principal funo dos ponteiros permitir a criao e a manipulao das variveis dinmicas, as quais iro compor as estruturas de dados dinmicas.

pgina 3

Estrutura de Dados 2 - Lzaro Eduardo da Silva

2.1 2.1.1

Ponteiros Declarao:A sintaxe de declarao de um tipo ponteiro o seguinte. Em Pascal type identificador = ^tipo; {onde o smbolo ^ indica que o identificador um ponteiro}

Em C tipo *identificador; /*onde o smbolo * indica que o identificador um ponteiro e o tipo ser (char, int, float, etc)*/ Isso indica que teremos um ponteiro com o nome de identificador com a capacidade de armazenar o endereo de memria de uma varivel desse tipo. Como os ponteiros so utilizados para implementar as estruturas de dados dinmicas, o mais comum em Pascal que seja criado um tipo do ponteiro desejado (type) e depois declaramos (var) as variveis ponteiro deste tipo. Em C, no se declara tipos. Exemplo: Em Pascal type Nome = string[35]; PontNome = ^Nome; var nome1 : PontNome; {o contedo apontado por nome1 do tipo string de tamanho 35} Em C char *p; /*o contedo do endereo apontado por p do tipo caracter*/

2.1.2

Inicializao:

Como os ponteiros armazenam endereos de memria, assim que eles so declarados o seu contedo um valor desconhecido (como as demais variveis), ou seja, no podemos prever para qual rea de memria este esta apontando, por isso, linguagens estruturadas permitem que um ponteiro seja inicializado, da seguinte forma: Em Pascal identificador := nil; {nil um valor nulo e pode ser armazenado em uma varivel do tipo apontador para indicar que a varivel no contm endereo de memria de nenhuma varivel dinmica } Em C identificador = null; {null um valor nulo e pode ser armazenado em uma varivel do tipo apontador para indicar que a varivel no contm endereo de memria de nenhuma varivel dinmica }

2.1.3

Criao de uma varivel dinmica:

Para criao de uma varivel dinmica necessrio que exista uma varivel do tipo apontador para o tipo da varivel que se deseja criar, cuja sintaxe a seguinte: Em Pascal new (identificador); {onde, identificador deve ser uma varivel do tipo ponteiro para o tipo de varivel a ser criada} Obs: quando uma varivel dinmica criada atravs da funo NEW, um espao de memria do tamanho da varivel criada alocado e este espao ficar alocado at ser liberado.

pgina 4

Estrutura de Dados 2 - Lzaro Eduardo da Silva

Em C Identificador = (tipo *) malloc (tamanho de memria a alocar); {onde, o tamanho da varivel pode ser encontrado com a funo sizeof(tipo). O tipo * indica o tipo de dado que o endereo de memria apontado por identificador pode receber}. Obs: A funo malloc, devolve o endereo do primeiro byte da memria alocado para uma varivel tipo ponteiro. Sempre que se alocar memria deve-se testar o valor devolvido por malloc (), antes de usar o ponteiro, para garantir que no nulo. Assim: char *p; if (!p=(char *) malloc (1000)){ puts(sem memria\n); exit(1); } foram alocados com esta instruo 1000 bytes de memria sendo que p aponta para o primeiro destes 1000 bytes. Um char foi alocado dinamicamente.

2.1.4

Destruio de uma varivel dinmica:

Para que o espao de memria seja liberado necessrio que a varivel dinmica seja destruda, utilizando a seguinte sintaxe; Em Pascal dispose (identificador); Em C free (identificador);

2.1.5

Referncia a uma varivel dinmica:

Quando uma varivel dinmica criada atravs de um ponteiro, este pode ser utilizado para referencila, permitindo a manipulao (leitura, atribuio, escrita, etc) desta varivel como outra varivel qualquer, observe o exemplo: Exemplo em Pascal program ManipulacaoVariaveisDinamicas; uses crt; type nome = string[30]; ponteiro = ^nome; var p1, p2 : ponteiro; begin new(p1); new(p2); readln(p1^); p2^ := 'Jos Maria'; p1^:= p1^ + ' ' + p2^; writeln(p1^); dispose(p1); dispose(p2); end. Exemplo em C #include #include #include

pgina 5

Estrutura de Dados 2 - Lzaro Eduardo da Silva

main() { char nome[30], *p1, *p2; p1=(char *)malloc(sizeof(nome)); p2=(char *)malloc(sizeof(nome)); gets(p1); p2 = "Jos Maria"; p1 = strcat(p1 , " "); p1 = strcat(p1 , p2); puts(p1); free(p1); free(p2); system("pause");

}Exerccios: 1. Um ponteiro pode ser usado para dizer a uma funo onde ela deve depositar o resultado de seus clculos. Escreva uma funo que converta minutos em horas-e-minutos. A funo recebe um inteiro mnts, duas variveis inteiras, digamos h e m, e atribui valores a essas variveis de modo que m seja menor que 60 e que 60*h + m seja igual a mnts. Escreva tambm um programa que use a funo. Escreva uma funo que receba um vetor inteiro v[0..n-1] e duas variveis inteiras, digamos min e max, e deposite nessas variveis o valor de um elemento mnimo e o valor de um elemento mximo do vetor. Escreva tambm um programa que use a funo.

2.

3

Pilhas e Filas

Algumas estruturas de dados disciplinam a forma como os elementos entram e saem destas estruturas. Pilhas e Filas so exemplos destas estruturas em que os elementos so inseridos e retirados de posies especiais. No caso da Pilha a disciplina de acesso utilizada recebe o nome de LIFO (Last In First Out), ou seja, o ltimo elemento a entrar na pilha tambm o primeiro que ser retirado no caso de uma remoo de um elemento desta estrutura. Todos os elementos na estrutura de dados Pilha so inseridos e retirados a partir de uma mesma posio denominada Topo da pilha. Para a Fila a disciplina de acesso utilizada a FIFO (First In First Out), o primeiro elemento que entra na fila ser tambm o primeiro elemento que sair da fila. A posio nesta estrutura por onde os elementos so inseridos recebe o nome de Fim da Fila, e a posio por onde os elementos so retirados desta estrutura recebe o nome de Comeo da Fila.

3.1

Pilha

Podemos implementar Pilha usando basicamente dois recursos presente nas principais linguagens de programao: Vetor Alocao dinmica de memria

3.1.1

Implementao de Pilha usando Alocao Dinmica de Memria

Um problema que normalmente acontece com as estruturas que usam do construtor de tipo vetor a limitao do nmero mximo de elementos que podemos ter. Para aplicaes em que necessitamos da estrutura de pilha, mas no podemos prever a quantidade de elementos que teremos, precisamos usar duas tcnicas: 1. Alocao dinmica de memria e 2. Encadeamento

pgina 6

Estrutura de Dados 2 - Lzaro Eduardo da Silva

Programa exemplo de alocao dinmica de memria: Programa Exemplo em Pascal program testa_alocacao_dinamica; type apontno = ^no; no = record info : char; prox : apontno; end; var p,q : apontno; c : char; begin q := nil; readln (c); new (p); p^.info := c; p^.prox := q; q := p; writeln (q^.info); dispose(p); readln; end. Programa Exemplo em C #include #include #include main() { struct no { char info; struct no *prox; }; struct no *p, *q; char c; q = NULL; scanf("%c", &c); p = (struct no *) malloc (sizeof (struct no)); p->info=c; p->prox=q; q=p; printf("%c",q->info); free(p); system("pause");

}Explicao do programa: 1. Na definio do tipo apontno estamos criando um tipo de varivel para guardar endereo de estruturas no. A estrutura no composta de dois campos, o campo info o campo responsvel por manter a informao na pilha e o campo prox o campo responsvel por possibilitar o encadeamento das informaes na pilha.

pgina 7

Estrutura de Dados 2 - Lzaro Eduardo da Silva

info

prox

2. A atribuio q := nil; guarda na varivel q um endereo nulo de memria. 3. A chamada da rotina de alocao dinmica de memria new(p); causa a criao de uma estrutura n para onde a varivel ponteiro p passa a apontar: p info prox

4. As atribuies p^.info := c; e p^.prox := q; guardam nos campos info e prox da estrutura n apontada por p os valores guardados nas variveis c e q respectivamente. p info % 5. A atribuio q := p; faz com que as variveis q e p contenham o mesmo endereo, i.e., os ponteiros q e p passam a apontar para a mesma estrutura no na memria. p info % prox prox

q 6. O comando de escrita writeln (q^.info); apresenta o valor guardado no campo info da estrutura apontada por q que tambm o valor no campo info da estrutura apontada por p pois ambos apontadores apontam para a mesma estrutura na memria.

Programa Exemplo em Pascal: program pilha_usando_alocacao; type apontno = ^no; no = record info : char; prox : apontno; end; var topo : apontno; valor : char; i : integer; procedure iniciapilha (var P : apontno); begin P := nil; end; procedure empilha (var P : apontno; D : char); var aux : apontno; begin new (aux); if (aux = nil) then writeln ('Overflow') else begin aux^.info := D; aux^.prox := P; P := aux;

pgina 8

Estrutura de Dados 2 - Lzaro Eduardo da Silva

end; end; procedure desempilha (var P : apontno; var D : char); var aux : apontno; begin if (P = nil) then writeln ('Underflow') else begin D := P^.info; aux := P; P := P^.prox; dispose (aux); end; end; begin iniciapilha (topo); writeln ('Empilhando...'); for i := 1 to 5 do begin valor := readkey; writeln (i,':', valor); empilha (topo, valor); end; writeln ('Desempilhando...'); for i := 1 to 6 do begin desempilha (topo, valor); writeln (i,':', valor); end; writeln ('Digite qualquer tecla...'); readln; end. Programa Exemplo em C: #include #include #include struct no { char info; struct no *prox; }; void iniciapilha(struct no **p) { *p = NULL; } void empilha(struct no **p, char d) { struct no *aux; aux = (struct no *) malloc (sizeof(no)); if(!aux) { puts ("Overflow!"); exit (0); }

pgina 9

Estrutura de Dados 2 - Lzaro Eduardo da Silva

else { aux->info = d; aux->prox = *p; *p = aux; } } int desempilha(struct no **p) { struct no *aux, *aux2; char d; if(!*p) { puts ("Underflow!"); return 0; } else { aux2=*p; d = aux2->info; aux = aux2; *p = aux2->prox; free(aux); return d; } } main() { struct no *p; int i; char valor; iniciapilha(&p); puts("Empilhando...\n"); for (i=1;icom = NULL;

pgina 12

Estrutura de Dados 2 - Lzaro Eduardo da Silva

F->fim = NULL; } void inserefila (struct fila *F, char *v) { struct no *t; t = (struct no *) malloc (sizeof (struct no)); if (!t) printf ("\nFILA CHEIA"); else { strcpy(t->info, v); t->lig = NULL; if (F->fim) { F->fim->lig = t; } F->fim = t; if (!F->com){ F->com = t; } } } void retirafila (struct fila *F, char *v) { struct no *t; if (!F->com) { puts ("\nFILA VAZIA"); strcpy(v," "); } else { t = F->com; strcpy(v, t->info); F->com = t->lig; if (!F->com) F->fim = NULL; free(t); } } main (void) { int i; char valor[20]; struct fila B; iniciafila (&B); for (i=1;ilig; } aux = p; strcpy(aux->info, v); if (!ant) { aux->lig = L->com; L->com = aux; } else { aux->lig = ant->lig; ant->lig = aux; } }

pgina 24

Estrutura de Dados 2 - Lzaro Eduardo da Silva

} void retiralista(struct lista *L, char *v) { struct no *aux, *ant, *p; if (L->com == NULL) { puts("Lista Vazia"); system("pause"); } else { ant=NULL; aux=L->com; while (aux != NULL && strcmp (aux->info,v) < 0) { ant=aux; aux=aux->lig; } if(aux==NULL || strcmp(aux->info,v)>0) { printf("Valor %s nao encontrado\n",v); system("pause"); } else { if(aux==L->com) { p=L->com; L->com=L->com->lig; free(p); } else { p=ant->lig; ant->lig=aux->lig; free(p); } } } } char leopcao() { char o; printf ("MENU\n"); printf ("1. Insere\n"); printf ("2. Remove\n"); printf ("3. Apresenta\n"); printf ("4. Fim\n"); printf ("Opcao: \n"); o = getchar(); return o; } main () { struct lista L; char nome[20];

pgina 25

Estrutura de Dados 2 - Lzaro Eduardo da Silva

char o; inicialista (&L); do { system("cls"); o = leopcao(); switch (o) { case '1' : scanf ("%s", nome); inserelista (&L, nome); break; case '2' : scanf ("%s", nome); retiralista(&L, nome); break; case '3' : printf ("Lista: "); mostralista(L); break; } }while (o != '4'); } Exerccios: 1. 2. Escreva uma funo para contar quantos elementos existem numa lista encadeada. Escreva um programa que utilize esta funo. Implemente uma funo para escrever a informao contida no ltimo n da lista. Escreva um programa que utilize esta funo.

pgina 26

Estrutura de Dados 2 - Lzaro Eduardo da Silva

5

Recursividade

Segundo Tenenbaum, um procedimento ou funo chamado recursivo quando na sua implementao existe uma chamada do prprio procedimento ou funo. Esta chamada recebe o nome de chamada recursiva. Em termos gerais, ao enfrentar a tarefa de escrever um programa para resolver um problema, no se preocupe em procurar uma soluo recursiva. A maioria dos problemas pode ser solucionada de maneira simples, usando mtodos no-recursivos. Entretanto, alguns problemas podem ser resolvidos em termos lgicos e com mais elegncia por meio da recursividade. A recursividade utilizada para simplificar a lgica de programao. Quase sempre substitui uma repetio, e como tal deve ter uma condio que determine a interrupo da repetio. Podemos dividir uma rotina recursiva em duas partes bsicas: A condio de parada da recursividade chamada(s) recursiva(s) Exemplo: Clculo de Fatorial. Esta operao matemtica definida de forma recursiva: 0! = 1 n! = (n-1)! * n p/ n > 0 Ento: 4! = 3! * 4 = 2! * 3 * 4 = 1! * 2 * 3 * 4 = 0! * 1 * 2 * 3 * 4 = 1 * 1 * 2 * 3 * 4 = 24 Programa Exemplo em Pascal: program exemplo_recursao; function fat (n : integer) : integer; begin if (n = 0) then fat := 1 else fat := fat(n-1) * n; end; begin writeln ('Fatorial de 4 = ', fat(4)); writeln ('Fatorial de 6 = ', fat(6)); readln; end. Programa Exemplo em C: #include int fat (int n) { if (n == 0) return 1; else return n * fat(n-1); } main () { printf ("O fatorial de %d e %d\n", 4, fat(4)); printf ("O fatorial de %d e %d\n", 6, fat(6));

pgina 27

Estrutura de Dados 2 - Lzaro Eduardo da Silva

getchar(); } n=4 24 6 fat(n-1) * 4 n=3 2 n=2 1 n=1 1 fat(n-1) * 1 0 n=0

fat(n-1) * 3 fat(n-1) * 2

No exemplo acima, quando o programa faz a chamada da funo fat enviando o valor 4, na funo o valor ir realizar o else com uma chamada da mesma funo enviando o valor 3. Quando esta chamada realizada, o retorno da funo fica pendente, visto que ela precisa do retorno da chamada com valor 3 para realizar a multiplicao por 4. Isso se repete, at que o valor enviado a funo seja zero, enviando como retorno o valor 1. Quando este retorno acontece, as multiplicaes pendentes so realizadas, tendo como retorno total da chamada inicial o resultado da multiplicao 1 * 1 * 2 * 3 * 4. Exerccios: 1. Faa uma funo recursiva SOMA que devolve o total da soma de todos os nmeros numa lista por alocao dinmica de nmeros. 2. Escreva um procedimento recursivo DISPLAY que mostra todos os elementos de uma lista encadeada por alocao dinmica. 3. Escreva uma funo recursiva para determinar o MDC (maior divisor comum) entre dois nmeros naturais x e y, baseando-se nas regras abaixo. Em seguida apresente uma verso iterativa do algoritmo capaz de realizar a mesma tarefa. mdc (x,y) = x mdc (x,y) = mdc (x-y,y) mdc (x,y) = mdc (x,y-x) se x = y se x > y se y > x

Escreva uma verso iterativa (no recursiva) da funo para calcular fatorial.

5.1

O problema das Torres de Hanoi

Um problema muito famoso que pode simplificar sua implementao utilizando a tcnica de recursividade as torres de Hani. H muito e muito tempo atrs, no alto das montanhas de Hanoi, havia um mosteiro onde habitavam sacerdotes brmanes; entre eles, era praticado um ritual para predizer o fim do mundo. Conta a lenda, que no mosteiro havia trs torres, sendo que na primeira delas estavam empilhados 64 discos de ouro em tamanhos decrescentes. Os sacerdotes acreditavam que quando eles terminassem de transferir todos os discos da primeira torre para a terceira (usando a segunda), sem nunca colocar um disco maior sobre um menor, ento, neste dia, o mundo acabaria! Para solucionar o problema das Torres de Hanoi, usando recurso, considere um caso geral em que n discos devem ser transferidos. Podemos ento dividir o problema em dois casos mais simples para mover n discos: o primeiro ter soluo trivial, e o segundo ter soluo recursiva. Assim, para mover n discos da torre A para a torre C, usando a torre B como auxiliar, fazemos: Se n = 1, transfira o disco da torre A para torre C e pare;

pgina 28

Estrutura de Dados 2 - Lzaro Eduardo da Silva

Caso Contrrio: 1. Transfira n-1 discos da torre A para B, usando C como auxiliar; 2. Transfira o ltimo disco da torre A para a torre C; 3. Transfira n-1 discos da torre B para torre C, usando A como auxiliar; Programa Exemplo em Pascal: program recursao_hanoi; procedure hanoi (n:integer; origem, auxiliar, destino: char); begin if (n = 1) then writeln ('Mova disco 1 da torre ', origem, ' para ', destino) else begin hanoi (n-1, origem, destino, auxiliar); writeln ('Mova disco ', n, ' da torre ', origem, ' para ', hanoi (n-1, auxiliar, origem, destino); end; end; begin hanoi (4, 'A', 'B', 'C'); readln; end. Programa Exemplo em C: #include void hanoi (int n, char a, char b, char c) { if (n == 1) printf ("\n mover 1 de %c para %c", a, c); else { hanoi (n-1, a, c, b); printf ("\n mover %d de %c para %c", n, a, c); hanoi (n-1, b, a, c); } } main (void) { hanoi (4, 'A', 'B', 'C'); getchar (); } Vamos verificar o funcionamento das torres de Hanoi para cinco discos de diferentes dimetros na torre A, de modo que um disco maior fique sempre abaixo de um disco menor. O objetivo deslocar os cinco discos para a torre C, usando a torre B como auxiliar. Somente o primeiro disco de toda a torre pode ser deslocado para outra torre, e um disco maior no pode nunca ficar posicionado sobre um disco menor (Tenenbaum, 2005).

destino);

pgina 29

Estrutura de Dados 2 - Lzaro Eduardo da Silva

A

B

C

Disco 1

Disco 2

Disco 3

Disco 4

Disco 5

Para deslocarmos os dois primeiros discos da torre A para a torre B usando C como auxiliar, basta deslocarmos o disco 1 da torre A para a torre C, deslocarmos o disco 2 da torre B e deslocarmos o disco 1 para a torre B em cima do disco 2. Poderamos deslocar o disco 3 da torre A para a torre C e, aplicar novamente a soluo para dois discos, movendo-os de B para C usando A como auxiliar. Como pargrafo acima, sabemos como deslocar os trs primeiros discos da torre A para a torre C usando B como auxiliar. Poderamos deslocar o quarto disco da torre A para a torre B e, aplicar novamente a soluo de trs discos, movendo-os de C para B, usando a torre A como auxiliar. Como pargrafo acima, sabemos como deslocar os quatro primeiros discos da torre A para a torre B usando C como auxiliar. Poderamos deslocar o maior disco de A para C e, por ltimo, aplicar novamente a soluo aos quatro discos, movendo-os de B para C, usando a torre A como auxiliar. Perceba a recursividade nos pargrafos acima. Cada pargrafo caracteriza as instrues da rotina conforme programa apresentado. Em geral, uma verso no-recursiva de um programa executar com mais eficincia, em termos de tempo e espao, do que uma verso recursiva. Isso acontece porque o trabalho extra dispendido para entrar e sair de um bloco evitado na verso no-recursiva. Contudo, verificamos que uma soluo recursiva o mtodo mais natural e lgico de solucionar um problema. Dessa forma, ocorre um conflito entre a eficincia da mquina e a do programador. Com o custo da programao aumentando consideravelmente e o custo da computao diminuindo, chegamos ao ponto em que, na maioria dos casos, no compensa para o programador construir exaustivamente uma soluo norecursiva (Tenenbaum, 2005).

pgina 30

Estrutura de Dados 2 - Lzaro Eduardo da Silva

6

rvore

A rvore uma estrutura de dados que caracteriza a hierarquia entre seus dados. Devido a isto, a estrutura indicada para aplicaes onde necessrio representar ordem e hierarquia. Representao esquemtica: b a c

d

e

f

g Terminologia:

h

i

j

k

A raiz desta rvore o n a. Mas todo n a raiz de uma subrvore. Ento b a raiz de uma subrvore que tem dois ns d e e, d a raiz de uma subrvore vazia. O nmero de subrvores de um n o grau daquele n. Ento a tem grau 2. Um n de grau zero um n folha ou n terminal. Ento d uma folha desta rvore. O nvel do n raiz zero. O demais nveis so definidos pelo nmero de ramos que o ligam com o n raiz. O n e, por exemplo, tem nvel 2. Floresta um conjunto de duas ou mais rvores. Exerccio: Para a rvore anterior encontre o grau, o nvel dos ns e quais so os ns folha e raiz. n a b c d e f g h i j k Grau nvel observao

pgina 31

Estrutura de Dados 2 - Lzaro Eduardo da Silva

Quando a ordem das subrvores relevante, dizemos que a rvore ordenada. Caso contrrio dizemos que uma rvore orientada.

6.1

rvore BinriaSo estruturas do tipo rvore, onde o grau de cada n menor ou igual a dois.

Exemplo: a b c

d

e

f

Existe numa rvore binria, distino entre a subrvore direita e esquerda. Ento para o exemplo anterior de rvore binria, a subrvore direita do n a comea com o n c e a subrvore esquerda comea com o n b.

6.1.1

Caminhamento em rvore Binria

Caminhar em uma rvore binria significa percorrer todos os ns da rvore de forma sistemtica de modo que cada n seja visitado uma nica vez. Existem 3 formas bsicas de caminhamento em rvore binria: 1. Caminhamento pr-fixado (pr-ordem) Processar o n Percorrer a subrvore esquerda Percorrer a subrvore direita 2. Caminhamento central (em-ordem) Percorrer a subrvore esquerda Processar o n Percorrer a subrvore direita 3. Caminhamento ps-fixado (ps-ordem) Percorrer a subrvore esquerda Percorrer a subrvore direita Processar o n Exemplo: Os ns da rvore binria anterior so processados da seguinte forma segundo cada caminhamento: pr-ordem: a, b, d, e, c, f em-ordem: d, b, e, a, c, f ps-ordem: d, e, b, f, c, a

pgina 32

Estrutura de Dados 2 - Lzaro Eduardo da Silva

Exerccio: Escreva quais so os resultados dos caminhamentos pr-ordem, em-ordem e ps-ordem para as seguintes rvores: A) a b c B) a b d

d

e

c

e

f C) a b

g D)

f

a b

c

c

f

d

d

e

g

6.1.2

Construo de rvore Binria:

Usaremos uma forma seqencial dos ns para facilitar o processo de construo de uma rvore binria. Suponha que os elementos da rvore aparecem em pr-ordem e que um ponto representa uma subrvore vazia. Assim a seqncia abg..c.de.f.... representa a seguinte rvore binria: a b g c d e f Exerccios: Represente as rvores correspondentes s seguintes seqncias: 1. a b . . c d . . e . . 2. a b d . . . c . e . .

pgina 33

Estrutura de Dados 2 - Lzaro Eduardo da Silva

3. a b c . . . . 4. a .b . c . . Escreva a seqncia em pr-ordem de construo da seguinte rvore binria: A) a b c B) a b d

d

e

c

e

f

g

f

6.1.3

Insero, Remoo e Consulta ordenada em rvore Binria:

A estrutura de rvore binria indicada para manuteno ordenada de dados. Assim, se usarmos o critrio que dados maiores devem ser inseridos no ramo direito e que os dados menores devem ser inseridos no ramo esquerdo, a rvore quando percorrida em-ordem ter todos os seus dados ordenados. Insero em rvore Binria: A insero dos valores 4, 2, 1, 3, 7, 5 e 8 usando o critrio citado anteriormente d como resultado a seguinte rvore binria: 4 2 1 3 5 7 8

Esta rvore percorrida em-ordem d como resultado estes dados ordenados: 1, 2, 3, 4, 5, 7 e 8. Observe que para toda subrvore temos os dados maiores que o n raiz direita e os dados menores que o n raiz esquerda. Assim, os valores maiores que 4 (5,7 e 8) esto direita. O valor 1 que menor que 2 est esquerda de 2. Remoo da rvore Binria: Para remover um n de uma rvore temos que analisar dois casos: Caso 1: O n a ser removido possui uma ou ambas subrvores vazias. Neste caso a remoo feita com a ligao do subramo esquerdo ou direito com o prximo n. Exemplo: 4 2 1 3 5 7 N a remover 1 2 3 4 5

Caso 2: Nenhuma das subrvores do n vazia. Neste caso o n a ser removido deve ser substitudo pelo smbolo seguinte na ordem a qual a rvore est organizada. O smbolo seguinte pode ser, por exemplo, o

pgina 34

Estrutura de Dados 2 - Lzaro Eduardo da Silva

menor dos maiores, ou seja, aquele que contm o menor valor da subrvore direita do n a ser removido. Exemplo: N a remover 2 1 3 5 4 7 8 1 2 3 5 7 8

Consulta da rvore Binria: Para procurar um n na rvore basta acompanhar a ordenao dos elementos em relao ao valor procurado. Ento, por exemplo, para procurar o valor 3 na rvore binria ordenada anterior, compara-se 3 com a raiz (4), 3 menor que 4, logo o valor 3 se estiver presente na rvore binria estar na subrvore esquerda do n 4. Esta verificao acontece at que o valor procurado seja encontrado ou que seja alcanada uma subrvore vazia. Programa Exemplo em Pascal: program Arvore_Binaria; uses crt; type arvore = ^no; no = record esq : arvore; info : char; dir : arvore; end; var a : arvore; op : integer; car: char; procedure constroi (var a : arvore); var c: char; begin c := readkey; write (c); if c = '.' then a := nil else begin new (a); a^.info := c; constroi (a^.esq); constroi (a^.dir); end; end; procedure destroi (var a : arvore); begin if a nil then begin destroi (a^.esq); destroi (a^.dir); dispose (a); a := nil;

pgina 35

Estrutura de Dados 2 - Lzaro Eduardo da Silva

end; end; procedure insere (var a : arvore; c : char); begin if a nil then begin if c > a^.info then insere (a^.dir, c) else insere (a^.esq, c); end else begin new (a); a^.info := c; a^.dir := nil; a^.esq := nil; end; end; function inter (p : arvore) : arvore; var r,s : arvore; begin r := p^.dir; s := r; while r nil do begin s := r; r := r^.esq; end; inter := s; end; procedure retira (var a : arvore; c : char); var p, q : arvore; begin p := a; q := nil; while (p^.info c) and (p nil) do begin q := p; if c < p^.info then p := p^.esq else p := p^.dir; end; if p = nil then begin writeln ('No nao encontrado'); end else begin if p^.esq = nil then begin if q = nil then a := p^.dir else

pgina 36

Estrutura de Dados 2 - Lzaro Eduardo da Silva

begin if q^.esq = p then q^.esq := p^.dir else q^.dir := p^.dir; dispose (p); end end else begin if p^.dir = nil then begin if q = nil then a := p^.esq else begin if q^.esq = p then q^.esq := p^.esq else q^.dir := p^.esq; dispose (p); end end else begin q := inter (p); p^.info := q^.info; retira (p^.dir, q^.info); end; end; end; end; procedure pre_ordem (a : arvore); begin if a nil then begin write (a^.info); pre_ordem (a^.esq); pre_ordem (a^.dir); end end; procedure em_ordem (a : arvore); begin if a nil then begin em_ordem (a^.esq); write (a^.info); em_ordem (a^.dir); end end; procedure pos_ordem (a : arvore); begin if a nil then begin pos_ordem (a^.esq);

pgina 37

Estrutura de Dados 2 - Lzaro Eduardo da Silva

pos_ordem (a^.dir); write (a^.info); end end; begin write('Digite uma sequencia (ex: ab..cd..e..): '); constroi (a); writeln; write ('Pre-ordem: ');; pre_ordem (a); writeln; write ('Em-ordem.: '); em_ordem (a); writeln; write ('Pos-ordem: '); pos_ordem (a); writeln; destroi (a); insere (a, '4'); insere (a, '2'); insere (a, '1'); insere (a, '3'); insere (a, '7'); insere (a, '5'); insere (a, '8'); write ('Em ordem.: '); em_ordem (a); writeln; retira (a, '1'); write ('Em ordem.: '); em_ordem (a); writeln; retira (a, '4'); write ('Em ordem.: '); em_ordem (a); readln; end. Programa Exemplo em C: #include #include #include struct arv { char info[30]; struct arv *dir; struct arv *esq; }; struct arv *constroi (void); void preordem (struct arv *no); void posordem (struct arv *no);

pgina 38

Estrutura de Dados 2 - Lzaro Eduardo da Silva

void ordeminter (struct arv *no); void destroi (struct arv *no); void mostra (struct arv *no, int nivel); int menu (void); void escreve (char *s); main () { struct arv *ARVORE = NULL; int escolha; do { escolha = menu (); switch (escolha) { case 0: puts ("Constroi arvore\n\r"); destroi (ARVORE); ARVORE = constroi (); break; case 1: puts ("Pre'-ordem\n\r"); preordem (ARVORE); break; case 2: puts ("Pos ordem\n\r"); posordem (ARVORE); break; case 3: puts ("Ordem intermediaria\n\r"); ordeminter (ARVORE); break; case 4: puts ("Mostra arvore\n\r"); mostra (ARVORE, 0); break; } puts ("\n\nDigite qualquer tecla..."); getchar (); } while (escolha != 5); destroi (ARVORE); } int menu (void) { int opcao; system("cls"); puts ("Opcoes:"); puts ("-------"); puts ("0. Constroi arvore"); puts ("1. Mostra arvore em Pre'-ordem"); puts ("2. Mostra arvore em Pos-ordem"); puts ("3. Mostra arvore em Ordem-intermediaria"); puts ("4. Desenha a arvore");

pgina 39

Estrutura de Dados 2 - Lzaro Eduardo da Silva

puts ("5. Fim de operacoes\n\n"); do { printf ("Escolha [0,1,2,3,4 ou 5]: "); opcao = getchar () - 48; getchar (); puts ("\n\n"); } while ((opcao < 0) && (opcao > 5)); return opcao; } struct arv * constroi (void) { struct arv *no; char auxstr[30]; fgets (auxstr, 29, stdin); auxstr[strlen (auxstr) - 1] = '\0'; if (strcmp (auxstr, ".") == 0) return NULL; else { no = (struct arv*) malloc (sizeof (struct arv)); strcpy (no->info, auxstr); no->esq = constroi (); no->dir = constroi (); return no; } } void preordem (struct arv *no) { if (no) { puts (no->info); preordem (no->esq); preordem (no->dir); } } void posordem (struct arv *no) { if (no) { posordem (no->esq); posordem (no->dir); puts (no->info); } } void

pgina 40

Estrutura de Dados 2 - Lzaro Eduardo da Silva

ordeminter (struct arv *no) { if (no) { ordeminter (no->esq); puts (no->info); ordeminter (no->dir); } } void destroi (struct arv *no) { if (no) { destroi (no->esq); destroi (no->dir); free (no); no = NULL; } } void mostra (struct arv *no, int nivel) { int i; if (no) { mostra (no->dir, nivel + 1); for (i = 0; i < nivel; i++) printf (" "); puts (no->info); mostra (no->esq, nivel + 1); } }

pgina 41

Estrutura de Dados 2 - Lzaro Eduardo da Silva

7

Mtodos de Classificao

Classificao ou ordenao de dados uma das tarefas mais freqentes e importantes em processamento de dados. A importncia da classificao de dados pode ser avaliada se considerarmos o que seria o problema de localizao do nome de um assinante em uma lista telefnica, na qual os nomes no estivessem em ordem alfabtica. O processo de classificao de um conjunto de dados inteiramente contido na memria primria chamado de classificao interna, ao passo que a classificao de um conjunto de dados no inteiramente armazenado na memria primria chamada de classificao externa. Existem 3 mtodos gerais para classificao interna de dados: classificao por troca classificao por seleo classificao por insero Para entender estes mtodos suponha o problema de ordenao das cartas do baralho. Classificao por troca: Espalhe as cartas numa mesa voltadas para cima e ento troque as cartas de ordem at que todo o baralho esteja ordenado. Classificao por Seleo: Espalhe as cartas na mesa, selecione a carta de menor valor, retire-a do baralho e segure-a na sua mo. Este processo continua at que todas as cartas estejam na sua mo. Classificao por Insero: Segure todas as cartas na sua mo. Ponha uma carta por vez na mesa, sempre inserindo na posio correta. O mao estar ordenado quando no restarem mais cartas em sua mo.

7.1

Classificao por Troca

Estes mtodos caracterizam-se por efetuarem a classificao por comparao sucessiva de pares de elementos, trocando-os de posio caso estejam fora da ordem desejada. Programa exemplo Pascal: program ordena_por_troca; const MAX = 20; var vetor: array [1..MAX] of integer; troca: boolean; i, salva: integer; begin randomize; writeln ('ORDENACAO POR TROCA'); writeln ('Antes da Ordenacao'); writeln ('------------------'); for i := 1 to MAX do begin vetor[i] := random (100); if (i < MAX) then write (vetor[i], ', ') else writeln (vetor[i], '.'); end; troca := true; while troca do begin troca := false;

pgina 42

Estrutura de Dados 2 - Lzaro Eduardo da Silva

for i := 1 to MAX-1 do begin if (vetor[i] > vetor[i+1]) then begin salva := vetor[i]; vetor[i] := vetor[i+1]; vetor[i+1] := salva; troca := true; end; end; end; writeln ('Depois da Ordenacao'); writeln ('-------------------'); for i := 1 to MAX do if (i < MAX) then write (vetor[i],', ') else writeln (vetor[i], '.'); readln; end. Programa exemplo C: #include #include #include #define MAX 20 int main() { int vetor[MAX], i, salva; bool troca; printf("ORDENACAO POR TROCA\n\n"); printf("Antes da Ordenacao\n"); printf("-------------------\n"); for(i=0;i