Anda di halaman 1dari 49

Prof.

Lzaro Eduardo da Silva

Apostila de Estrutura de Dados 2

Bacharelado em Cincia da Computao

2009
3 Perodo

Estrutura de Dados 2 - Lzaro Eduardo da Silva

Sumrio
1 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

5 6

pgina 2

Estrutura de Dados 2 - Lzaro Eduardo da Silva

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.

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 <stdio.h> #include <string.h> #include <stdlib.h>

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.

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 <stdio.h> #include <string.h> #include <stdlib.h> 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 <stdio.h> #include <stdlib.h> #include <conio.h> 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;i<=5;i++) { valor = getch(); printf (" %d: %c\n", i , valor); empilha (&p, valor); } puts ("Desempilhando...\n"); for (i=1;i<=6;i++) { valor=desempilha (&p); printf (" %d: %c\n", i , valor); } system("pause"); return 0; } Exerccios: 1. Escreva uma funo que use uma pilha para inverter a ordem das letras de cada palavra de uma string, preservando a ordem das palavras. Por exemplo, dado o texto ESTE EXERCICIO E MUITO FACIL a sada deve ser ETSE OICICREXE E OTIUM LICAF. Escreva um programa que utilize esta funo.

pgina 10

Estrutura de Dados 2 - Lzaro Eduardo da Silva

2.

Suponha que queremos decidir se uma dada seqncia de parnteses e colchetes est bem formada. Construa uma funo que verifique se uma expresso foi digitada corretamente, utilizando as rotinas de Pilha implementadas acima. Escreva um programa que utilize esta funo.

3.2

Fila

Como j foi discutido, a fila assim como a pilha so estruturas de dados cujos dados entram e saem segundo disciplinas de acesso. A diferena bsica entre a pilha e a fila que na pilha temos uma nica extremidade por onde os elementos so inseridos e retirados (topo da pilha). No caso da fila os elementos entram por uma extremidade (fim da fila) e saem por outra (comeo da fila). Assim como para a Pilha, a Fila tambm pode ser implementada usando basicamente dois recursos de programao: Vetor Alocao dinmica de memria

3.2.1

Implementao de Fila usando Alocao Dinmica de Memria

A Estrutura: com fim

info

prox

info

prox

info

prox

Programa Exemplo Pascal: program fila_usando_alocacao; uses crt; type pontno = ^no; no = record info : string; lig : pontno; end; fila = record com : pontno; fim : pontno; end; var B : fila; valor : string; i : integer; procedure iniciafila (var F : fila); begin F.com := nil; F.fim := nil; end; procedure inserefila (var F : fila; D : string); var t : pontno; begin new (t); t^.info := D;

pgina 11

Estrutura de Dados 2 - Lzaro Eduardo da Silva

t^.lig := nil; if F.fim <> nil then F.fim^.lig := t; F.fim := t; if F.com = nil then F.com := t; end; procedure retirafila (var F : fila; var D : string); var t : pontno; begin if F.com = nil then writeln ('Fila vazia') else begin t := F.com; D := t^.info; F.com := t^.lig; if F.com = nil then F.fim := nil; dispose (t); end; end; (*------ Programa Principal -------*) begin clrscr; iniciafila (B); for i := 1 to 5 do begin readln (valor); inserefila (B, valor); end; for i := 1 to 6 do begin retirafila (B, valor); writeln (i:2,'-> ', valor); end; writeln ('Digite qualquer tecla...'); readln; end. Programa Exemplo C: #include <stdio.h> #include <stdlib.h> #include <string.h> struct no { char info[30]; struct no *lig; }; struct fila { struct no *com; struct no *fim; }; void iniciafila (struct fila *F) { F->com = 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;i<=5;i++) { gets(valor); inserefila (&B, valor); } for (i=1;i<=6;i++) { retirafila (&B, valor); printf (" %d: %s\n", i , valor); } system("pause"); } Exerccios:

pgina 13

Estrutura de Dados 2 - Lzaro Eduardo da Silva

1.

Escreva uma funo que devolva o comprimento (ou seja, o nmero de elementos) de uma fila dada. Escreva um programa que atravs de um menu gerencie as primitivas da Fila, inclusive a nova funo implementada. Implemente uma funo que utilizando a estrutura de Fila preencha gradativamente a partir de um ponto inicial os vizinhos mais prximos de uma matriz.

2.

Listas Lineares

a estrutura que permite representar um conjunto de dados de forma a preservar a relao de ordem linear que existe entres estes dados. Uma lista linear composta de ns, os quais podem conter, cada um deles, um dado primitivo ou um dado composto. Define-se uma lista linear como sendo o conjunto de n 0 de ns x1, x2, ..., xn, organizados estruturalmente de forma a refletir as posies relativas dos mesmos. Se n > 0 ento x1 o primeiro n; para 1 < k < n, o n k precedido pelo n xk-1 e seguido do n xk+1; e xn o ltimo n. Quando n = 0, dizemos que a lista vazia. Operaes Primitivas: 1. Inicializar uma lista 2. Inserir um n na lista 3. Remover um n da lista 4. Consultar um n da lista Representaes de Listas: Podemos implementar listas lineares de duas formas: 1. Por contiguidade dos ns: usando o construtor de tipo vetor. 2. Por encadeamento dos ns: usando vetor ou alocao dinmica de memria.

4.1

Listas Lineares por Encadeamento

No caso da representao de listas lineares por contigidade dos ns, dois problemas foram detectados: 1. O nmero mximo de elementos fica limitado ao tamanho do vetor. 2. Algumas operaes primitivas comprometem o desempenho da lista, pois implicam num grande esforo computacional para cumprir suas especificaes. Por exemplo, para insero de um elemento na primeira posio de uma lista com 2.000 elementos armazenados. Nesta situao so necessrias 2.000 atribuies para gerar espao para o novo primeiro elemento da lista. Para resolver o segundo problema (complexidade das operaes de insero e remoo), podemos usar a tcnica de encadeamento j discutida para implementao de fila e pilha. A tcnica de encadeamento pode ser implementada usando-se o vetor. Mas neste caso continuamos com o primeiro problema, a estrutura de lista continua limitada para o mximo nmero de elementos do vetor utilizado na sua declarao Duas novas implementaes da estrutura de dados lista linear ser apresentada: 1. Lista Linear Encadeada usando Vetor 2. Lista Linear Encadeada usando Alocao Dinmica de Memria.

pgina 14

Estrutura de Dados 2 - Lzaro Eduardo da Silva

4.1.1

Lista Linear Encadeada usando Vetor:

A Estrutura: Info 1 com 2 2 3 4 5 dispo 6 6 7 8 Dirceu Alberto Carlos Bruno Lig -1 4 1 3 7 5 8 -1

Cada elemento da lista um registro com dois campos: info (informao) utilizado para armazenar os valores da lista, e o campo lig (ligao) utilizado para prover o encadeamento da lista. Cada elemento indica qual o elemento que vem em seguida atravs do valor no campo lig. O valor -1 marca o fim da lista. O comeo da lista de posies disponveis da estrutura est indicada na varivel dispo, e o comeo da lista propriamente dita est indicado na varivel com. Para esta nova representao o processo de insero e remoo de ns na lista simplificado pelo simples acerto de ligaes.

Operaes Primitivas: Insero: Antes de inserir BB: info lig AA info lig CC Depois da insero info lig AA info lig CC info lig BB Remoo: Antes de remover BB: info lig AA info lig BB info lig CC info lig AA Depois da remoo info lig BB info lig CC

Programa Exemplo em Pascal: program lista_encadeada_vetor_simulacao;

pgina 15

Estrutura de Dados 2 - Lzaro Eduardo da Silva

uses crt; type no = record info : char; lig : integer; end; type lista = array [1..8] of no; procedure escxy (x, y: integer; s: string); begin gotoxy (x, y); write (s); end; procedure msg (m : string); var t : char; begin escxy (33,24,m); escxy (33,25,'Digite qualquer tecla...'); t := readkey; gotoxy (1,24); clreol; gotoxy (1,25); clreol; end; procedure representa (x,y:integer; l:lista; c,d:integer); var i : integer; begin escxy (x,y, ' 1 2 3 4 5 6 7 8 '); escxy (x,y+1,' +-------------------------------+'); escxy (x,y+2,'L info'); escxy (x,y+3,' +---+---+---+---+---+---+---+---'); escxy (x,y+4,' lig'); escxy (x,y+5,' +-------------------------------+'); for i := 1 to 8 do begin escxy (x+4*i,y+2,l[i].info); gotoxy (x+4*i,y+4); write (l[i].lig); end; escxy (x+8,y+7,' +---+ +---+'); gotoxy(x+8,y+8); write('com ',c:2,' dispo ',d:2,' '); escxy (x+8,y+9,' +---+ +---+'); end; procedure insere (var l:lista; var c, d:integer; n:char); var aux, ant : integer; begin if d = -1 then msg ('Lista cheia') else begin aux := c; ant := -1; while (l[aux].info<=n) and (aux<>-1) do begin ant := aux; aux := l[aux].lig; end; aux := d; d := l[d].lig; l[aux].info := n;

pgina 16

Estrutura de Dados 2 - Lzaro Eduardo da Silva

if ant = -1 then begin l[aux].lig := c; c := aux; end else begin l[aux].lig := l[ant].lig; l[ant].lig := aux; end; end; end; procedure remove (var l:lista; var c, d:integer; n:char); var aux, ant: integer; begin if c = -1 then msg ('lista vazia') else begin aux := c; ant := -1; while (aux <> -1) and (l[aux].info<>n) do begin ant := aux; aux := l[aux].lig; end; if aux = -1 then msg ('Nome nao encontrado') else begin if aux = c then c := l[c].lig else l[ant].lig := l[aux].lig; l[aux].lig := d; l[aux].info := ' '; d := aux; end; end; end; procedure inicialista (var l:lista; var c, d:integer); var i:integer; begin for i := 1 to 8 do begin l[i].info := ' '; l[i].lig := i+1; end; l[8].lig := -1; c := -1; d := 1; end; function leopcao : char; var o : char; begin textcolor (lightblue); textbackground (lightgray);

pgina 17

Estrutura de Dados 2 - Lzaro Eduardo da Silva

escxy (33,1,' ----MENU---- '); escxy (33,2,' 1. Insere '); escxy (33,3,' 2. Remove '); escxy (33,4,' 3. Fim '); textcolor (lightgray); textbackground (black); escxy (33,6,'Opcao: '); o := readkey; escxy (40,6,o); leopcao := o; end; function lenome (r : string) : char; begin escxy (33,8,r); escxy (33,9,'Caracter: '); lenome := readkey; gotoxy (33,8); clreol; gotoxy (33,9); clreol; end; var x : lista; o : char; com, dispo : integer; begin inicialista (x, com, dispo); clrscr; repeat representa (23,11,x,com,dispo); o := leopcao; case o of '1' : insere (x, com, dispo, lenome ('INSERCAO')); '2' : remove (x, com, dispo, lenome ('REMOCAO')); end; until o = '3'; end. Programa Exemplo em C: #include <conio.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 8 struct no { char info; int lig; }; void inicialista (struct no *L, int *COM, int *DISPO) { int i; for (i = 0; i< MAX; i++) { L[i].info = '\0'; L[i].lig = i+1; }

pgina 18

Estrutura de Dados 2 - Lzaro Eduardo da Silva

L[MAX-1].lig=-1; *COM = -1; *DISPO = 0; } void inserelista (struct no *L, int *COM, int *DISPO, char *v) { int aux, ant; if(*DISPO == -1) { printf ("\nlista cheia\n"); system("pause"); } else { ant = -1; aux = *COM; while (aux != -1 && (L[aux].info <= *v)) { ant = aux; aux = L[aux].lig; } aux = *DISPO; *DISPO = L[aux].lig; L[aux].info = *v; if(ant == -1) { L[aux].lig = *COM; *COM = aux; } else { L[aux].lig = L[ant].lig; L[ant].lig = aux; } } } void retiralista(struct no *L, int *com, int *dispo, char *s) { int aux, ant; if (*com == -1) { puts("Lista Vazia"); system("pause"); } else { aux=*com; ant=-1; while (aux != -1 && (L[aux].info != *s)) { ant=aux; aux=L[aux].lig; } if(aux==-1) { printf("\nValor %c nao encontrado\n",s);

pgina 19

Estrutura de Dados 2 - Lzaro Eduardo da Silva

system("pause"); } else { if(aux==*com) *com=L[*com].lig; else L[ant].lig=L[aux].lig; L[aux].lig=*dispo; *dispo=aux; L[aux].info='\0'; } } } void representa (struct no *l, int c, int d) { int i; printf("\n 0 1 2 3 4 5 6 7 \n"); printf(" +-------------------------------+\n"); printf("L "); for (i=0; i<MAX; i++) { printf ("| %c ",l[i].info); } printf("| info\n"); printf(" +---+---+---+---+---+---+---+---\n"); printf(" "); for (i=0; i<MAX; i++) { if(l[i].lig==-1) printf ("|%d ",l[i].lig); else printf ("| %d ",l[i].lig); } printf("| lig\n"); printf(" +-------------------------------+\n"); printf (" +---+ +---+\n"); printf ("com | %d | dispo | %d |\n",c,d); printf (" +---+ +---+\n"); } char leopcao() { char o; printf ("MENU\n"); printf ("1. Insere\n"); printf ("2. Remove\n"); printf ("3. Fim\n"); printf ("Opcao: \n"); o = getch(); return o; } char lenome() { char val; printf ("\nCaracter: "); val=getch();

pgina 20

Estrutura de Dados 2 - Lzaro Eduardo da Silva

return (val); } main () { struct no L[MAX]; int c, d; char nome; char o; inicialista (L, &c, &d); do { system("cls"); representa (L,c,d); o = leopcao(); switch (o) { case '1' : printf("Inserir"); nome=lenome(); inserelista (L, &c, &d, &nome); break; case '2' : printf("Remover"); nome=lenome(); retiralista(L, &c, &d, &nome); break; } }while (o != '3'); } Exerccios: 1. 2. Escreva uma funo que concatena duas listas encadeadas. Escreva um programa que utilize esta funo. Escreva uma funo que busque um valor em uma lista encadeada e informe em que posio este valor est. Escreva um programa que utilize esta funo.

4.1.2

Lista Encadeada usando Alocao Dinmica de Memria

Conseguimos atravs do encadeamento resolver o segundo problema relacionado com a lista por contigidade, o baixo desempenho das primitivas de insero e remoo de n na lista devido ao grande nmero de operaes necessrias para estes processos. Com o recurso de alocao dinmica de memria conseguimos resolver o primeiro problema, ou seja, limitao do tamanho da lista. Programa Exemplo em Pascal: program lista_encadeada_por_alocacao; uses crt; type lista = ^no; no = record info : string; lig : lista; end; procedure escxy (x, y: integer; s: string); begin gotoxy (x, y); write (s); end;

pgina 21

Estrutura de Dados 2 - Lzaro Eduardo da Silva

procedure msg (m : string); var t : char; begin escxy (1,24,m); escxy (1,25,'Digite qualquer tecla...'); t := readkey; end; procedure insere (var l:lista; n:string); var aux, ant : lista; begin aux := l; ant := nil; while (aux <> nil) and (aux^.info<=n) do begin ant := aux; aux := aux^.lig; end; new (aux); aux^.info := n; if ant = nil then begin aux^.lig := l; l := aux; end else begin aux^.lig := ant^.lig; ant^.lig := aux; end; end; procedure remove (var l:lista; n:string); var aux, ant: lista; begin if l = nil then msg ('lista vazia') else begin aux := l; ant := nil; while (aux^.info<>n) and (aux<>nil) do begin ant := aux; aux := aux^.lig; end; if aux = nil then msg ('Nome nao encontrado') else begin if aux = l then l := l^.lig else ant^.lig := aux^.lig; dispose (aux); end; end; end;

pgina 22

Estrutura de Dados 2 - Lzaro Eduardo da Silva

procedure inicialista (var l:lista); begin l := nil; end; procedure mostra (l:lista); begin while (l <> nil) do begin write (l^.info, ', '); l := l^.lig; end; msg ('Fim da lista'); end; function leopcao : char; var o : char; begin textcolor (lightblue); textbackground (lightgray); escxy (1,1,' ----MENU---- '); escxy (1,2,' 1. Insere '); escxy (1,3,' 2. Remove '); escxy (1,4,' 3. Apresenta '); escxy (1,5,' 4. Fim '); textcolor (lightgray); textbackground (black); escxy (1,7,'Opcao: '); o := readkey; escxy (7,7,o); leopcao := o; end; function lenome (r : string) : string; var s : string; begin escxy (1,9,r); escxy (1,10,'Nome: '); readln (s); lenome := s; end; var x : lista; o : char; begin inicialista (x); repeat clrscr; o := leopcao; case o of '1' : insere (x, lenome ('INSERCAO')); '2' : remove (x, lenome ('REMOCAO')); '3' : begin escxy (1,9,'LISTA: '); mostra (x);

pgina 23

Estrutura de Dados 2 - Lzaro Eduardo da Silva

end; end; until o = '4'; end. Programa Exemplo em C: #include <stdio.h> #include <stdlib.h> #include <string.h> struct no { char info[30]; struct no *lig; }; struct lista { struct no *com; }; void inicialista (struct lista *L) { L->com = NULL; } void mostralista (struct lista L) { struct no *aux; aux = L.com; while (aux) { printf ("%s ", aux->info); aux = aux->lig; } printf("\n"); system("pause"); } void inserelista (struct lista *L, char *v) { struct no *aux, *ant, *p; p = (struct no *) malloc (sizeof (struct no)); if (!p) { printf ("\nLISTA CHEIA"); system("pause"); } else { ant = NULL; aux = L->com; while (aux != NULL && strcmp (aux->info,v) < 0) { ant = aux; aux = aux->lig; } 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

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 <stdio.h> 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 <stdio.h> 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

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

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

g Terminologia:

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 Binria
So estruturas do tipo rvore, onde o grau de cada n menor ou igual a dois.

Exemplo: a b c

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

f C) a b

g D)

a b

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

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 <stdio.h> #include <stdlib.h> #include <string.h> 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

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 <stdio.h> #include <stdlib.h> #include <string.h> #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<MAX;i++) { vetor[i]=rand()%100; if(i<(MAX-1)) printf("%d, ",vetor[i]); else printf("%d.\n",vetor[i]); } troca=true; while (troca) { troca = false; for (i=0;i<(MAX-1);i++) { if (vetor[i] > vetor[i+1]) { salva = vetor[i]; vetor[i] = vetor[i+1]; vetor[i+1] = salva; troca = true; } } }

pgina 43

Estrutura de Dados 2 - Lzaro Eduardo da Silva

printf ("\nDepois da Ordenacao\n"); printf ("-------------------\n"); for (i=0;i<MAX;i++) if (i < (MAX-1)) printf ("%d, ",vetor[i]); else printf ("%d.\n\n",vetor[i]); system("pause"); } Para o vetor <50,73,54,89,22,46,91,11,29,2> a seqncia de passos que ser executado por este mtodo para ordenao do vetor : 50 50 50 50 22 22 22 11 11 2 2 73 54 54 22 46 46 11 22 2 11 11 54 73 22 46 50 11 29 2 22 22 22 89 22 46 54 11 29 2 29 29 29 29 22 46 73 11 29 2 46 46 46 46 46 46 89 11 29 2 50 50 50 50 50 50 91 11 29 2 54 54 54 54 54 54 54 11 29 2 73 73 73 73 73 73 73 73 29 2 89 89 89 89 89 89 89 89 89 2 91 91 91 91 91 91 91 91 91 91

Obs: O nome Bubble (bolha) deve-se ao fato que durante o processo de ordenao como se os valores menores fossem as bolhas flutuando para ocupar as primeiras posies no vetor.

7.2

Classificao por Seleo

Nestes mtodos, a classificao efetivada por seleo sucessiva do menor valor dentro do vetor. A cada passo o elemento de menor valor colocado em sua posio definitiva no vetor classificado e o processo repetido para o segmento que contm os elementos ainda no selecionados. Programa exemplo em Pascal: program ordena_por_selecao; const MAX = 20; var vetor: array [1..MAX] of integer; i, j, menor, salva: integer; begin randomize; writeln ('ORDENACAO POR SELECAO'); 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; for i := 1 to MAX-1 do begin menor := i;

pgina 44

Estrutura de Dados 2 - Lzaro Eduardo da Silva

for j := i+1 to MAX do if (vetor[j] < vetor[menor]) then menor := j; salva := vetor[i]; vetor[i] := vetor[menor]; vetor[menor] := salva; 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 em C: #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 20 int main() { int vetor[MAX], i, j, menor, salva; printf("ORDENACAO POR SELECAO\n\n"); printf("Antes da Ordenacao\n"); printf("-------------------\n"); for(i=0;i<MAX;i++) { vetor[i]=rand()%100; if(i<(MAX-1)) printf("%d, ",vetor[i]); else printf("%d.\n",vetor[i]); } for(i=0;i<MAX-1;i++) { menor = i; for(j=i+1;j<MAX;j++) if (vetor[j] < vetor[menor]) menor = j; salva = vetor[i]; vetor[i] = vetor[menor]; vetor[menor] = salva; } printf ("\nDepois da Ordenacao\n"); printf ("-------------------\n"); for (i=0;i<MAX;i++) if (i < (MAX-1)) printf ("%d, ",vetor[i]); else printf ("%d.\n\n",vetor[i]); system("pause"); }

pgina 45

Estrutura de Dados 2 - Lzaro Eduardo da Silva

Para o vetor <52,75,36,20,17,46,60,78,51,80> a seqncia de passos que ser executado por este mtodo para ordenao do vetor : 52 17 17 17 17 17 17 17 17 75 75 20 20 20 20 20 20 20 36 36 36 36 36 36 36 36 36 20 20 75 75 46 46 46 46 46 17 52 52 52 52 51 51 51 51 46 46 46 46 75 75 52 52 52 60 60 60 60 60 60 60 60 60 78 78 78 78 78 78 78 78 75 51 51 51 51 51 52 75 75 78 80 80 80 80 80 80 80 80 80

7.3

Classificao por Insero

A caracterstica comum de todos os mtodos de classificao por insero que eles efetivam a ordenao do vetor pela insero de cada um dos elementos em sua posio dentro de um subvetor classificado. Programa exemplo em Pascal: program ordena_por_insercao; const MAX = 20; var vetor: array [0..MAX] of integer; i, j, x, salva: integer; begin randomize; writeln ('ORDENACAO POR INSERCAO'); 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; i := 2; while i <= MAX do begin x := vetor[i]; vetor[0] := vetor[i]; j := i-1; while x < vetor[j] do begin vetor[j+1] := vetor[j]; j := j-1; end; vetor[j+1] := x; i := i+1; end; writeln ('Depois da Ordenacao'); writeln ('-------------------'); for i := 1 to MAX do if (i < MAX)

pgina 46

Estrutura de Dados 2 - Lzaro Eduardo da Silva

then write (vetor[i],', ') else writeln (vetor[i], '.'); readln; end. Programa exemplo em C: #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 20 int main() { int vetor[MAX], i, j, x, salva; printf("ORDENACAO POR SELECAO\n\n"); printf("Antes da Ordenacao\n"); printf("-------------------\n"); for(i=1;i<=MAX;i++) { vetor[i]=rand()%100; if(i<MAX) printf("%d, ",vetor[i]); else printf("%d.\n",vetor[i]); } i = 2; while (i < MAX) { x = vetor[i]; vetor[0] = vetor[i]; j = i-1; while (x < vetor[j]) { vetor[j+1] = vetor[j]; j = j-1; } vetor[j+1] = x; i = i+1; } printf ("\nDepois da Ordenacao\n"); printf ("-------------------\n"); for (i=1;i<=MAX;i++) if (i < MAX) printf ("%d, ",vetor[i]); else printf ("%d.\n\n",vetor[i]); system("pause"); } Para o vetor <33,69,12,80,36,46,94,71,30,74> a seqncia de passos que ser executado por este mtodo para ordenao do vetor : 33 33 12 12 69 69 33 33 12 12 69 69 80 80 80 80 36 36 36 36 46 46 46 46 94 94 94 94 71 71 71 71 30 30 30 30 74 74 74 74

pgina 47

Estrutura de Dados 2 - Lzaro Eduardo da Silva

12 12 12 12 12 12 Exerccios:

33 33 33 33 30 30

36 36 36 36 33 33

69 46 46 46 36 36

80 69 69 69 46 46

46 80 80 71 69 69

94 94 94 80 71 71

71 71 71 94 80 74

30 30 30 30 94 80

74 74 74 74 74 94

1. Implemente uma funo que conte o nmero de trocas necessrias para cada algoritmo de classificao. Escreva um programa que utilize esta funo. 2. Experimente inserir valores inversos e verifique qual o melhor algoritmo de classificao para esta situao. Para julgar a eficincia dos algoritmos utilize a funo implementada na questo anterior.

pgina 48

Estrutura de Dados 2 - Lzaro Eduardo da Silva

Bibliografia

KNUTH, D.E., The art of computer programming, vol 1 Fundamental algorithms, Addison Wesley, USA, 1997.

PEREIRA, SLVIO DO LAGO - Estrutura de Dados Fundamentais: conceitos e aplicaes, rica, So Paulo, 1996.

PIMENTEL, Graa. Material didtico da disciplina Algoritmos e Estruturas de Dados. Disponvel em http://www.icmc.usp.br/~sce182/.

SZWARCFITER, JAYME LUIZ - Estrutura de Dados e seus algoritmos, LTC, Rio de Janeiro, 1994.

TENENBAUM, AARON M., LANGSAM, YEDIDYAH, AUGENSTEIN, MOSHE J. Estrutura de Dados usando C, Makron Books, So Paulo, 2005.

VELOSO, PAULO, SANTOS, CLSIO DOS, AZEREDO, PAULO e FURTADO, ANTNIO - Estrutura de Dados, Campus, Rio de Janeiro, 1986.

VILLAS, MARCOS VIANA - Estrutura de Dados: conceitos e tcnicas de implementao, Campus, Rio de Janeiro, 1993.

ZIVIANI, N., Projeto de Algoritmos: com implementaes em Pascal e C, 4a Ed., So Paulo, Pioneira, 1999.

Textos Clssicos:

HOROWITZ, E. and SAHNI, S. - Fundamentals of Data Structures, Calif., Computer Science Press, 1975.

WIRTH, N. - Algorithms + Data Structures = Programs, N.J., Prentice Hall, 1976.

AHO, A.V., HOPCROFT, J.E. and ULMAN J.D. - Data Structures and Algorithms, Mass., Addison-Wesley, 1983.

pgina 49