Prof.

Lázaro Eduardo da Silva

Apostila de Estrutura de Dados 2

Bacharelado em Ciência da Computação

2009
3º Período

Estrutura de Dados 2 - Lázaro Eduardo da Silva

Sumário
1 2 INTRODUÇÃO ............................................................................................................... 3 TIPO APONTADOR (PONTEIRO)............................................................................... 3 2.1 PONTEIROS................................................................................................................ 4 2.1.1 Declaração: ........................................................................................................ 4 2.1.2 Inicialização: ...................................................................................................... 4 2.1.3 Criação de uma variável dinâmica: ................................................................... 4 2.1.4 Destruição de uma variável dinâmica: .............................................................. 5 2.1.5 Referência a uma variável dinâmica:................................................................. 5 PILHAS E FILAS ........................................................................................................... 6 3.1 PILHA ........................................................................................................................ 6 3.1.1 Implementação de Pilha usando Alocação Dinâmica de Memória ................... 6 3.2 FILA ......................................................................................................................... 11 3.2.1 Implementação de Fila usando Alocação Dinâmica de Memória ................... 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 Alocação Dinâmica de Memória ............................. 21 RECURSIVIDADE ....................................................................................................... 27 5.1 O PROBLEMA DAS TORRES DE HANOI .................................................................... 28 ÁRVORE ....................................................................................................................... 31 6.1 ÁRVORE BINÁRIA ................................................................................................... 32 6.1.1 Caminhamento em Árvore Binária ................................................................... 32 6.1.2 Construção de Árvore Binária: ........................................................................ 33 6.1.3 Inserção, Remoção e Consulta ordenada em Árvore Binária: ........................ 34 MÉTODOS DE CLASSIFICAÇÃO ............................................................................. 42 7.1 CLASSIFICAÇÃO POR TROCA .................................................................................. 42 7.2 CLASSIFICAÇÃO POR SELEÇÃO .............................................................................. 44 7.3 CLASSIFICAÇÃO POR INSERÇÃO ............................................................................. 46 BIBLIOGRAFIA........................................................................................................... 49

3

4

5 6

7

8

página 2

Estrutura de Dados 2 - Lázaro Eduardo da Silva

1

Introdução

A automatização de tarefas é um aspecto marcante da sociedade moderna e na ciência da computação houve um processo de desenvolvimento simultâneo e interativo de máquinas (hardware) e dos elementos que gerenciam a execução automática (software) de uma tarefa. Nesta grande evolução do mundo computacional, um fator de relevante importância é a forma de armazenar as informações, já que, informática é a ciência da informação. Então de nada adiantaria o grande desenvolvimento do hardware e do software, se a forma de armazenamento e tratamento da informação não acompanhasse esse desenvolvimento. Por isso a importância das estruturas de dados, que nada mais são, que formas otimizadas de armazenamento e tratamento das informações 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 são que a transformação 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 atuação ótima. Um algoritmo é um processo sistemático para resolução de um problema. O desenvolvimento de algoritmos é particularmente importante para problemas a serem solucionados em um computador, pela própria natureza do instrumento utilizado. Um algoritmo computa uma saída, o resultado do problema, a partir de uma entrada, as informações inicialmente conhecidas e permitem encontrar a solução do problema. Durante o processo de computação, o algoritmo manipula dados, gerados a partir de sua entrada. Quando os dados são manipulados de uma forma homogênea, constituem um tipo abstrato de dados. Este é composto por um modelo matemático acompanhado por um conjunto de operações definido sobre este modelo. Um algoritmo é projetado em termos de tipos abstratos de dados. Para implementá-los numa linguagem de programação, é necessário encontrar uma forma de representá-los nessa linguagem, utilizando-se tipos e operações suportadas pelo computador. Na representação do modelo matemático emprega-se uma estrutura de dados. As estruturas diferem uma das outras pela disposição ou manipulação de seus dados. A disposição dos dados em uma estrutura obedece a condições preestabelecidas e caracteriza a estrutura. Até aqui, as estruturas apresentadas eram estáticas (vetores e matrizes). Agora novas estruturas de dados serão apresentadas, sendo que, todas elas serão estruturas de dados dinâmicas, ou seja, crescem e diminuem de acordo com a necessidade, veremos que, para isso, serão necessárias várias rotinas que controlam esta dinamicidade das estruturas.

2

Tipo Apontador (Ponteiro)

Um das características mais marcantes de linguagens estruturadas é permitir a criação e destruição de variáveis durante a execução do programa. O uso dessas variáveis possibilita a implementação das estruturas de dados dinâmicas. Essas variáveis criadas e destruídas durante a execução do programa são chamadas variáveis dinâmicas. Uma variável dinâmica não é declarada na parte de declaração de variáveis porque esta ainda não existe antes do seu tempo de execução, ela não possui sequer um nome, ficando a cargo dos ponteiros desempenharem esta função de “nome”. Uma variável dinâmica é sempre referenciada indiretamente por um apontador, ou seja, para cada variável dinâmica criada deve existir um apontador, que literalmente aponta para ela, permitindo a sua manipulação. Os apontadores são declarados como as demais variáveis, seguindo a sintaxe da linguagem de programação utilizada. Eles são variáveis que armazenam o endereço de memória de outras variáveis, funcionando assim, como meio de referenciar uma variável dinâmica, permitindo o acesso a essa variável. Outra característica dos apontadores é que na sua declaração deve ser indicado qual o tipo de variável este irá armazenar o endereço. A principal função dos ponteiros é permitir a criação e a manipulação das variáveis dinâmicas, as quais irão compor as estruturas de dados dinâmicas.

página 3

Estrutura de Dados 2 - Lázaro Eduardo da Silva

2.1 2.1.1

Ponteiros Declaração:
A sintaxe de declaração de um tipo ponteiro é o seguinte. Em Pascal type identificador = ^tipo; {onde o símbolo ^ indica que o identificador é um ponteiro}

Em C tipo *identificador; /*onde o símbolo * 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 endereço de memória de uma variável desse tipo. Como os ponteiros são utilizados para implementar as estruturas de dados dinâmicas, o mais comum em Pascal é que seja criado um tipo do ponteiro desejado (type) e depois declaramos (var) as variáveis ponteiro deste tipo. Em C, não se declara tipos. Exemplo: Em Pascal type Nome = string[35]; PontNome = ^Nome; var nome1 : PontNome; {o conteúdo apontado por nome1 é do tipo string de tamanho 35} Em C char *p; /*o conteúdo do endereço apontado por p é do tipo caracter*/

2.1.2

Inicialização:

Como os ponteiros armazenam endereços de memória, assim que eles são declarados o seu conteúdo é um valor desconhecido (como as demais variáveis), ou seja, não podemos prever para qual área de memória 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 variável do tipo apontador para indicar que a variável não contém endereço de memória de nenhuma variável dinâmica } Em C identificador = null; {null é um valor nulo e pode ser armazenado em uma variável do tipo apontador para indicar que a variável não contém endereço de memória de nenhuma variável dinâmica }

2.1.3

Criação de uma variável dinâmica:

Para criação de uma variável dinâmica é necessário que exista uma variável do tipo apontador para o tipo da variável que se deseja criar, cuja sintaxe é a seguinte: Em Pascal new (identificador); {onde, identificador deve ser uma variável do tipo ponteiro para o tipo de variável a ser criada} Obs: quando uma variável dinâmica é criada através da função NEW, um espaço de memória do tamanho da variável criada é alocado e este espaço ficará alocado até ser liberado.

página 4

Estrutura de Dados 2 . O tipo * indica o tipo de dado que o endereço de memória apontado por identificador pode receber}. Um char foi alocado dinamicamente.1. uses crt. para garantir que não é nulo. begin new(p1).h> #include <stdlib. p2 : ponteiro. dispose(p1). 2. type nome = string[30]. if (!p=(char *) malloc (1000)){ puts(“sem memória\n”).4 Destruição de uma variável dinâmica: Para que o espaço de memória seja liberado é necessário que a variável dinâmica seja destruída. este pode ser utilizado para referenciála. end.Lázaro Eduardo da Silva Em C Identificador = (tipo *) malloc (tamanho de memória a alocar). observe o exemplo: Exemplo em Pascal program ManipulacaoVariaveisDinamicas. Obs: A função malloc. antes de usar o ponteiro. } foram alocados com esta instrução 1000 bytes de memória sendo que p aponta para o primeiro destes 1000 bytes. etc) desta variável como outra variável qualquer. Exemplo em C #include <stdio. exit(1).5 Referência a uma variável dinâmica: Quando uma variável dinâmica é criada através de um ponteiro. Em C free (identificador). p1^:= p1^ + ' ' + p2^. var p1. p2^ := 'José Maria'. atribuição. dispose(p2). utilizando a seguinte sintaxe. ponteiro = ^nome. o tamanho da variável pode ser encontrado com a função sizeof(tipo). readln(p1^). writeln(p1^). {onde. escrita. Assim: char *p. Sempre que se alocar memória deve-se testar o valor devolvido por malloc (). Em Pascal dispose (identificador). new(p2). 2.h> #include <string. permitindo a manipulação (leitura.1.h> página 5 . devolve o endereço do primeiro byte da memória alocado para uma variável tipo ponteiro.

Escreva uma função que converta minutos em horas-e-minutos.Lázaro Eduardo da Silva main() { char nome[30]. No caso da Pilha a disciplina de acesso utilizada recebe o nome de LIFO (Last In First Out).1 Implementação de Pilha usando Alocação Dinâmica de Memória Um problema que normalmente acontece com as estruturas que usam do construtor de tipo vetor é a limitação do número máximo de elementos que podemos ter. digamos min e max. } Exercícios: 1.Estrutura de Dados 2 . puts(p1). 3 Pilhas e Filas Algumas estruturas de dados disciplinam a forma como os elementos entram e saem destas estruturas. Para a Fila a disciplina de acesso utilizada é a FIFO (First In First Out). 2. free(p2). mas não podemos prever a quantidade de elementos que teremos. Pilhas e Filas são exemplos destas estruturas em que os elementos são inseridos e retirados de posições especiais. Todos os elementos na estrutura de dados Pilha são inseridos e retirados a partir de uma mesma posição denominada Topo da pilha.. A função recebe um inteiro mnts. p1 = strcat(p1 . o último elemento a entrar na pilha é também o primeiro que será retirado no caso de uma remoção de um elemento desta estrutura. ou seja. 3. " "). duas variáveis inteiras. free(p1). system("pause"). p1 = strcat(p1 . Encadeamento página 6 . p1=(char *)malloc(sizeof(nome)). Escreva uma função que receba um vetor inteiro v[0. *p2.1 Pilha Podemos implementar Pilha usando basicamente dois recursos presente nas principais linguagens de programação: • Vetor • Alocação dinâmica de memória 3. o primeiro elemento que entra na fila será também o primeiro elemento que sairá da fila. precisamos usar duas técnicas: 1. Um ponteiro pode ser usado para dizer a uma função onde ela deve depositar o resultado de seus cálculos. *p1. gets(p1). digamos h e m. p2=(char *)malloc(sizeof(nome)). p2 = "José Maria". Escreva também um programa que use a função.n-1] e duas variáveis inteiras.1. e deposite nessas variáveis o valor de um elemento mínimo e o valor de um elemento máximo do vetor. e atribui valores a essas variáveis de modo que m seja menor que 60 e que 60*h + m seja igual a mnts. Escreva também um programa que use a função. Para aplicações em que necessitamos da estrutura de pilha. Alocação dinâmica de memória e 2. p2). A posição nesta estrutura por onde os elementos são inseridos recebe o nome de Fim da Fila. e a posição por onde os elementos são retirados desta estrutura recebe o nome de Começo da Fila.

char c. begin q := nil. type apontno = ^no. p->info=c. readln (c). readln. o campo info é o campo responsável por manter a informação na pilha e o campo prox é o campo responsável por possibilitar o encadeamento das informações na pilha. free(p). system("pause").h> main() { struct no { char info. new (p). struct no *prox.prox := q. c : char.Lázaro Eduardo da Silva Programa exemplo de alocação dinâmica de memória: Programa Exemplo em Pascal program testa_alocacao_dinamica.Estrutura de Dados 2 . prox : apontno. q = NULL.info).h> #include <string. *q. printf("%c". dispose(p).h> #include <stdlib. A estrutura no é composta de dois campos. writeln (q^. q := p. end. end. p->prox=q. no = record info : char. p = (struct no *) malloc (sizeof (struct no)). q=p. &c). Programa Exemplo em C #include <stdio. }. página 7 . } Explicação do programa: 1. p^.info := c. var p. p^.q : apontno. Na definição do tipo apontno estamos criando um tipo de variável para guardar endereço de estruturas no.q->info). scanf("%c". struct no *p.

valor : char. begin P := nil. guardam nos campos info e prox da estrutura nó apontada por p os valores guardados nas variáveis c e q respectivamente.info := c. no = record info : char. prox : apontno.Estrutura de Dados 2 . A chamada da rotina de alocação dinâmica de memória new(p). 3. end. O comando de escrita writeln (q^. página 8 ..prox := P. p info ‘%’ 5. e p^. Programa Exemplo em Pascal: program pilha_usando_alocacao. D : char).e. P := aux. type apontno = ^no.prox := q. begin new (aux). A atribuição q := nil. A atribuição q := p. var aux : apontno.info := D. procedure iniciapilha (var P : apontno). faz com que as variáveis q e p contenham o mesmo endereço.Lázaro Eduardo da Silva info prox 2. os ponteiros q e p passam a apontar para a mesma estrutura no na memória. apresenta o valor guardado no campo info da estrutura apontada por q que é também o valor no campo info da estrutura apontada por p pois ambos apontadores apontam para a mesma estrutura na memória. if (aux = nil) then writeln ('Overflow') else begin aux^. i. As atribuições p^. causa a criação de uma estrutura nó para onde a variável ponteiro p passa a apontar: p info prox 4.info). p info ‘%’ prox prox q 6. var topo : apontno. i : integer. end. aux^. procedure empilha (var P : apontno. guarda na variável q um endereço nulo de memória.

struct no *prox.. writeln ('Desempilhando.info. exit (0).. end. P := P^.h> #include <conio.'). end. writeln (i. begin if (P = nil) then writeln ('Underflow') else begin D := P^. valor).':'..h> struct no { char info. char d) { struct no *aux.'). aux := P.'). for i := 1 to 6 do begin desempilha (topo. valor). end. empilha (topo. for i := 1 to 5 do begin valor := readkey... valor). } página 9 . end.Estrutura de Dados 2 . procedure desempilha (var P : apontno. var aux : apontno. writeln ('Empilhando. writeln ('Digite qualquer tecla.':'.Lázaro Eduardo da Silva end. valor).. aux = (struct no *) malloc (sizeof(no)). begin iniciapilha (topo). dispose (aux).prox.h> #include <stdlib. if(!aux) { puts ("Overflow!"). writeln (i. var D : char). }. readln. } void empilha(struct no **p. Programa Exemplo em C: #include <stdio. end. end. void iniciapilha(struct no **p) { *p = NULL.

. puts("Empilhando. aux->prox = *p. valor). char valor.Lázaro Eduardo da Silva else { aux->info = d. *p = aux.Estrutura de Dados 2 .i++) { valor=desempilha (&p). Por exemplo.. i . } else { aux2=*p. } puts ("Desempilhando. iniciapilha(&p).i<=6. Escreva uma função que use uma pilha para inverter a ordem das letras de cada palavra de uma string. if(!*p) { puts ("Underflow!"). página 10 .i++) { valor = getch(). dado o texto ESTE EXERCICIO E MUITO FACIL a saída deve ser ETSE OICICREXE E OTIUM LICAF. int i. Escreva um programa que utilize esta função. valor). char d.\n"). } } main() { struct no *p.. } } int desempilha(struct no **p) { struct no *aux.i<=5. i . *aux2. printf (" %d: %c\n". valor). *p = aux2->prox. } Exercícios: 1. free(aux). for (i=1. d = aux2->info. aux = aux2. printf (" %d: %c\n".\n"). return d. return 0. } system("pause"). for (i=1. empilha (&p.. preservando a ordem das palavras. return 0.

valor : string.Lázaro Eduardo da Silva 2.2. fim : pontno. t^.com := nil. end. i : integer. página 11 .Estrutura de Dados 2 . var B : fila. procedure inserefila (var F : fila. A diferença básica entre a pilha e a fila é que na pilha temos uma única extremidade por onde os elementos são inseridos e retirados (topo da pilha). utilizando as rotinas de Pilha implementadas acima. lig : pontno. 3. D : string).fim := nil. fila = record com : pontno.2 Fila Como já foi discutido. begin new (t). F. a Fila também pode ser implementada usando basicamente dois recursos de programação: • Vetor • Alocação dinâmica de memória 3. Suponha que queremos decidir se uma dada seqüência de parênteses e colchetes está bem formada. Assim como para a Pilha. begin F. a fila assim como a pilha são estruturas de dados cujos dados entram e saem segundo disciplinas de acesso. Escreva um programa que utilize esta função. no = record info : string. type pontno = ^no.info := D. var t : pontno. end.1 Implementação de Fila usando Alocação Dinâmica de Memória A Estrutura: com fim info prox info prox info prox Programa Exemplo Pascal: program fila_usando_alocacao. procedure iniciafila (var F : fila). No caso da fila os elementos entram por uma extremidade (fim da fila) e saem por outra (começo da fila). Construa uma função que verifique se uma expressão foi digitada corretamente. uses crt. end.

readln. struct fila { struct no *com. (*-----.Lázaro Eduardo da Silva t^.h> struct no { char info[30]. if F. void iniciafila (struct fila *F) { F->com = NULL.Estrutura de Dados 2 . valor). if F.fim^.com.lig := nil.com := t^. iniciafila (B).fim <> nil then F. end. end. procedure retirafila (var F : fila. end. Programa Exemplo C: #include <stdio.h> #include <stdlib.com = nil then F.Programa Principal -------*) begin clrscr.. end.info. writeln ('Digite qualquer tecla. D := t^. struct no *lig.com := t. begin if F.fim := t.lig := t. página 12 . F.fim := nil. inserefila (B. end. if F.')..'-> '. valor). var D : string). }.com = nil then F. end.h> #include <string. for i := 1 to 5 do begin readln (valor). }. valor). F. writeln (i:2.com = nil then writeln ('Fila vazia') else begin t := F. struct no *fim.lig. var t : pontno. dispose (t). for i := 1 to 6 do begin retirafila (B.

inserefila (&B.Estrutura de Dados 2 . } void inserefila (struct fila *F. } system("pause"). if (!F->com){ F->com = t. } } } void retirafila (struct fila *F.i<=6. } for (i=1. iniciafila (&B)." "). for (i=1. char valor[20]. if (F->fim) { F->fim->lig = t. valor). struct fila B. else { strcpy(t->info. strcpy(v. if (!t) printf ("\nFILA CHEIA"). if (!F->com) { puts ("\nFILA VAZIA"). F->com = t->lig. i . free(t). printf (" %d: %s\n". char *v) { struct no *t. strcpy(v. } Exercícios: página 13 . } } main (void) { int i.i++) { retirafila (&B. } else { t = F->com. if (!F->com) F->fim = NULL. t->info). char *v) { struct no *t. valor). t->lig = NULL. valor). v).i++) { gets(valor). t = (struct no *) malloc (sizeof (struct no)).i<=5.Lázaro Eduardo da Silva F->fim = NULL. } F->fim = t.

Operações Primitivas: 1. 2.. pois implicam num grande esforço computacional para cumprir suas especificações. A técnica de encadeamento pode ser implementada usando-se o vetor. 2. Algumas operações primitivas comprometem o desempenho da lista. O número máximo de elementos fica limitado ao tamanho do vetor. organizados estruturalmente de forma a refletir as posições relativas dos mesmos. para 1 < k < n. xn.1 Listas Lineares por Encadeamento No caso da representação de listas lineares por contigüidade dos nós. a estrutura de lista continua limitada para o máximo número de elementos do vetor utilizado na sua declaração Duas novas implementações da estrutura de dados lista linear será apresentada: 1. x2. página 14 . dizemos que a lista é vazia. o número de elementos) de uma fila dada. Por exemplo. Por encadeamento dos nós: usando vetor ou alocação dinâmica de memória. 2. um dado primitivo ou um dado composto. Inicializar uma lista 2. dois problemas foram detectados: 1. . inclusive a nova função implementada.Estrutura de Dados 2 .Lázaro Eduardo da Silva 1. Escreva um programa que através de um menu gerencie as primitivas da Fila. para inserção de um elemento na primeira posição de uma lista com 2. Se n > 0 então x1 é o primeiro nó. e xn é o último nó. o nó k é precedido pelo nó xk-1 e é seguido do nó xk+1. Quando n = 0. Lista Linear Encadeada usando Alocação Dinâmica de Memória. Implemente uma função que utilizando a estrutura de Fila preencha gradativamente a partir de um ponto inicial os vizinhos mais próximos de uma matriz.000 elementos armazenados. 4 Listas Lineares É a estrutura que permite representar um conjunto de dados de forma a preservar a relação de ordem linear que existe entres estes dados. cada um deles. 4. Lista Linear Encadeada usando Vetor 2. Define-se uma lista linear como sendo o conjunto de n ≥ 0 de nós x1. Nesta situação são necessárias 2. Escreva uma função que devolva o comprimento (ou seja. Por contiguidade dos nós: usando o construtor de tipo vetor.. Inserir um nó na lista 3. os quais podem conter.. Para resolver o segundo problema (complexidade das operações de inserção e remoção). Remover um nó da lista 4.000 atribuições para gerar espaço para o novo primeiro elemento da lista. Mas neste caso continuamos com o primeiro problema. Uma lista linear é composta de nós. Consultar um nó da lista Representações de Listas: Podemos implementar listas lineares de duas formas: 1. podemos usar a técnica de encadeamento já discutida para implementação de fila e pilha.

e o começo da lista propriamente dita está indicado na variável com.1. página 15 .Lázaro Eduardo da Silva 4. O começo da lista de posições disponíveis da estrutura está indicada na variável dispo.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 (informação) utilizado para armazenar os valores da lista. O valor -1 marca o fim da lista. Para esta nova representação o processo de inserção e remoção de nós na lista é simplificado pelo simples acerto de ligações. Operações Primitivas: Inserção: Antes de inserir ‘BB’: info lig ‘AA’ info lig ‘CC’ Depois da inserção info lig ‘AA’ info lig ‘CC’ info lig ‘BB’ Remoção: Antes de remover ‘BB’: info lig ‘AA’ info lig ‘BB’ info lig ‘CC’ info lig ‘AA’ Depois da remoção info lig ‘BB’ info lig ‘CC’ Programa Exemplo em Pascal: program lista_encadeada_vetor_simulacao.Estrutura de Dados 2 . Cada elemento indica qual é o elemento que vem em seguida através do valor no campo lig. e o campo lig (ligação) utilizado para prover o encadeamento da lista.

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

var aux. begin if c = -1 then msg ('lista vazia') else begin aux := c. d := aux.lig. l[ant]. l[aux]. end. end.Estrutura de Dados 2 .lig. c := aux.lig := aux.lig := c. l[i]. end. end. begin textcolor (lightblue). var o : char. l[aux]. end else begin l[aux].info := ' '. end. var i:integer. end.Lázaro Eduardo da Silva if ant = -1 then begin l[aux]. end. if aux = -1 then msg ('Nome nao encontrado') else begin if aux = c then c := l[c]. página 17 . procedure inicialista (var l:lista.lig := l[ant]. l[8]. d := 1. procedure remove (var l:lista.lig := -1.lig else l[ant]. end.lig. textbackground (lightgray).lig := d. ant := -1.lig := i+1. while (aux <> -1) and (l[aux]. ant: integer. aux := l[aux]. var c. d:integer. n:char).lig := l[aux]. end. var c.info := ' '. c := -1. begin for i := 1 to 8 do begin l[i]. d:integer). function leopcao : char.info<>n) do begin ant := aux.

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

int *COM.info = *v. char *s) { int aux. ant. while (aux != -1 && (L[aux]. } if(aux==-1) { printf("\nValor %c nao encontrado\n".Lázaro Eduardo da Silva L[MAX-1]. ant. int *com. aux=L[aux]. int *DISPO. aux = *COM. if(*DISPO == -1) { printf ("\nlista cheia\n").info <= *v)) { ant = aux. char *v) { int aux.Estrutura de Dados 2 . } void inserelista (struct no *L. if (*com == -1) { puts("Lista Vazia"). system("pause"). if(ant == -1) { L[aux]. } } } void retiralista(struct no *L.lig = *COM. página 19 .lig.lig. int *dispo. *COM = aux. } else { ant = -1.lig=-1. while (aux != -1 && (L[aux]. system("pause"). *COM = -1. } else { L[aux].lig. *DISPO = 0. } else { aux=*com. L[aux].lig. ant=-1. L[ant].s). aux = L[aux]. } aux = *DISPO.lig = L[ant].lig = aux.info != *s)) { ant=aux. *DISPO = L[aux].

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

d). inicialista (L. end. s: string). retiralista(L. &nome).1. char o. ou seja. &c. o = leopcao(). Escreva um programa que utilize esta função. página 21 . char nome. int c. Escreva uma função que concatena duas listas encadeadas.Estrutura de Dados 2 . break. &c. no = record info : string. inserelista (L. &d. &d. end. case '2' : printf("Remover"). Escreva um programa que utilize esta função. Programa Exemplo em Pascal: program lista_encadeada_por_alocacao. y). Escreva uma função que busque um valor em uma lista encadeada e informe em que posição este valor está. uses crt. } Exercícios: 1. switch (o) { case '1' : printf("Inserir"). o baixo desempenho das primitivas de inserção e remoção de nó na lista devido ao grande número de operações necessárias para estes processos. } main () { struct no L[MAX]. nome=lenome(). Com o recurso de alocação dinâmica de memória conseguimos resolver o primeiro problema. &c. break. 2. nome=lenome(). &d). representa (L. procedure escxy (x. y: integer. begin gotoxy (x.2 Lista Encadeada usando Alocação Dinâmica de Memória Conseguimos através do encadeamento resolver o segundo problema relacionado com a lista por contigüidade. } }while (o != '3').Lázaro Eduardo da Silva return (val). lig : lista. do { system("cls"). d. limitação do tamanho da lista. write (s).c. &nome). 4. type lista = ^no.

end. l := aux. n:string). var aux. begin if l = nil then msg ('lista vazia') else begin aux := l.lig := ant^.'Digite qualquer tecla. aux := aux^. end. ant: lista.. procedure remove (var l:lista. end. n:string). t := readkey.Estrutura de Dados 2 . new (aux).info<=n) do begin ant := aux. end.'). begin escxy (1.m).lig. if aux = nil then msg ('Nome nao encontrado') else begin if aux = l then l := l^. begin aux := l. ant : lista. ant := nil. end. aux := aux^.. if ant = nil then begin aux^.lig := l. aux^. end. end. var aux.lig. end. dispose (aux).24. while (aux^. var t : char.lig. procedure insere (var l:lista.info := n.lig else ant^.info<>n) and (aux<>nil) do begin ant := aux.Lázaro Eduardo da Silva procedure msg (m : string).25.lig. end else begin aux^. ant^. página 22 .lig := aux^. while (aux <> nil) and (aux^. ant := nil.lig := aux. escxy (1.

Remove ').9.'Nome: '). begin l := nil. function lenome (r : string) : string.o).' 1. end. end. leopcao := o. escxy (1. Apresenta '). '). textcolor (lightgray).7.Estrutura de Dados 2 . readln (s). escxy (7. var s : string. var o : char. escxy (1. escxy (1.4. end. textbackground (lightgray). begin textcolor (lightblue). repeat clrscr. escxy (1. página 23 . l := l^. Insere '). begin escxy (1. begin while (l <> nil) do begin write (l^.'Opcao: ').info. '2' : remove (x. procedure mostra (l:lista).lig. mostra (x). Fim '). lenome ('INSERCAO')).2. o := readkey.3.1. escxy (1. end.10.7. o : char. '.'LISTA: '). case o of '1' : insere (x. function leopcao : char.').' 3. lenome ('REMOCAO')).' 4.5. escxy (1. var x : lista.r). '3' : begin escxy (1. msg ('Fim da lista'). textbackground (black).Lázaro Eduardo da Silva procedure inicialista (var l:lista).9.' 2. o := leopcao.' ----MENU---. end. begin inicialista (x). escxy (1. lenome := s.

} void inserelista (struct lista *L. } else { aux->lig = ant->lig. system("pause"). char *v) { struct no *aux. aux = aux->lig. aux = L. }. v). *ant. while (aux) { printf ("%s ". if (!ant) { aux->lig = L->com. } } página 24 . system("pause"). ant->lig = aux. strcpy(aux->info. aux = L->com.h> #include <stdlib. struct no *lig. void inicialista (struct lista *L) { L->com = NULL. L->com = aux. struct lista { struct no *com. aux = aux->lig. } printf("\n"). aux->info). if (!p) { printf ("\nLISTA CHEIA").h> #include <string.com. p = (struct no *) malloc (sizeof (struct no)). }.Estrutura de Dados 2 . until o = '4'. Programa Exemplo em C: #include <stdio. } aux = p. *p.Lázaro Eduardo da Silva end. end. while (aux != NULL && strcmp (aux->info. } else { ant = NULL. end. } void mostralista (struct lista L) { struct no *aux.h> struct no { char info[30].v) < 0) { ant = aux.

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

do { system("cls"). break. } }while (o != '4'). nome). retiralista(&L. switch (o) { case '1' : scanf ("%s".Lázaro Eduardo da Silva char o. nome). Escreva um programa que utilize esta função. 2.Estrutura de Dados 2 . Escreva uma função para contar quantos elementos existem numa lista encadeada. nome). } Exercícios: 1. inserelista (&L. break. inicialista (&L). Escreva um programa que utilize esta função. Implemente uma função para escrever a informação contida no último nó da lista. case '2' : scanf ("%s". o = leopcao(). página 26 . mostralista(L). nome). case '3' : printf ("Lista: "). break.

6. A recursividade é utilizada para simplificar a lógica de programação. Esta chamada recebe o nome de chamada recursiva. Esta operação matemática é definida de forma recursiva: 0! = 1 n! = (n-1)! * n p/ n > 0 Então: 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. Quase sempre substitui uma repetição. um procedimento ou função é chamado recursivo quando na sua implementação existe uma chamada do próprio procedimento ou função. } main () { printf ("O fatorial de %d e %d\n". end. e como tal deve ter uma condição que determine a interrupção da repetição. function fat (n : integer) : integer.h> int fat (int n) { if (n == 0) return 1.Estrutura de Dados 2 . alguns problemas podem ser resolvidos em termos lógicos e com mais elegância por meio da recursividade. fat(4)). Em termos gerais. begin writeln ('Fatorial de 4 = '. Entretanto. fat(4)). writeln ('Fatorial de 6 = '.Lázaro Eduardo da Silva 5 Recursividade Segundo Tenenbaum. begin if (n = 0) then fat := 1 else fat := fat(n-1) * n. ao enfrentar a tarefa de escrever um programa para resolver um problema. printf ("O fatorial de %d e %d\n". else return n * fat(n-1). 4. página 27 . Programa Exemplo em C: #include <stdio. A maioria dos problemas pode ser solucionada de maneira simples. readln. não se preocupe em procurar uma solução recursiva. usando métodos não-recursivos. fat(6)). Podemos dividir uma rotina recursiva em duas partes básicas: • A condição de parada da recursividade • chamada(s) recursiva(s) Exemplo: Cálculo de Fatorial. end. fat(6)).

as multiplicações pendentes são realizadas. no alto das montanhas de Hanoi. fazemos: • Se n = 1. usando a torre B como auxiliar. neste dia. Conta a lenda. Faça uma função recursiva SOMA que devolve o total da soma de todos os números numa lista por alocação dinâmica de números. Quando este retorno acontece. mdc (x. e o segundo terá solução recursiva. Exercícios: 1. era praticado um ritual para predizer o fim do mundo. Escreva uma função recursiva para determinar o MDC (maior divisor comum) entre dois números naturais x e y. 5. transfira o disco da torre A para torre C e pare. até que o valor enviado a função seja zero. página 28 .y) mdc (x. tendo como retorno total da chamada inicial o resultado da multiplicação 1 * 1 * 2 * 3 * 4.y) = x mdc (x. 2.Lázaro Eduardo da Silva getchar().y) = mdc (x. } 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. para mover n discos da torre A para a torre C. então. Assim. Os sacerdotes acreditavam que quando eles terminassem de transferir todos os discos da primeira torre para a terceira (usando a segunda). Em seguida apresente uma versão iterativa do algoritmo capaz de realizar a mesma tarefa. o retorno da função fica pendente. baseando-se nas regras abaixo.1 O problema das Torres de Hanoi Um problema muito famoso que pode simplificar sua implementação utilizando a técnica de recursividade é as torres de Hanói. sem nunca colocar um disco maior sobre um menor. quando o programa faz a chamada da função fat enviando o valor 4.y-x) se x = y se x > y se y > x Escreva uma versão iterativa (não recursiva) da função para calcular fatorial. enviando como retorno o valor 1. Quando esta chamada é realizada. na função o valor irá realizar o else com uma chamada da mesma função enviando o valor 3. visto que ela precisa do retorno da chamada com valor 3 para realizar a multiplicação por 4. Podemos então “dividir” o problema em dois casos mais simples para mover n discos: o primeiro terá solução trivial. “Há muito e muito tempo atrás. havia um mosteiro onde habitavam sacerdotes brâmanes. usando recursão. sendo que na primeira delas estavam empilhados 64 discos de ouro em tamanhos decrescentes. 3.y) = mdc (x-y. entre eles.Estrutura de Dados 2 . Escreva um procedimento recursivo DISPLAY que mostra todos os elementos de uma lista encadeada por alocação dinâmica. considere um caso geral em que n discos devem ser transferidos. que no mosteiro havia três torres. o mundo acabaria!” Para solucionar o problema das Torres de Hanoi. Isso se repete.

Transfira o último disco da torre A para a torre C. end. 'C'). b. auxiliar. auxiliar. readln. destino). begin if (n = 1) then writeln ('Mova disco 1 da torre '. usando a torre B como auxiliar. procedure hanoi (n:integer. } Vamos verificar o funcionamento das torres de Hanoi para cinco discos de diferentes diâmetros na torre A. 'B'. e um disco maior não pode nunca ficar posicionado sobre um disco menor (Tenenbaum. 2005). ' para '.Lázaro Eduardo da Silva • Caso Contrário: 1. destino). origem. Somente o primeiro disco de toda a torre pode ser deslocado para outra torre. 'A'. página 29 . writeln ('Mova disco '. b). n.h> void hanoi (int n. Programa Exemplo em C: #include <stdio. else { hanoi (n-1. de modo que um disco maior fique sempre abaixo de um disco menor. Programa Exemplo em Pascal: program recursao_hanoi. origem. 'A'. a. usando C como auxiliar. O objetivo é deslocar os cinco discos para a torre C. 3. c. usando A como auxiliar. a. c).Estrutura de Dados 2 . printf ("\n mover %d de %c para %c". 'B'. ' para '. char a. a. a. end. c). c). hanoi (n-1. origem. destino) else begin hanoi (n-1. origem. Transfira n-1 discos da torre A para B. n. char c) { if (n == 1) printf ("\n mover 1 de %c para %c". hanoi (n-1. end. ' da torre '. auxiliar). destino. begin hanoi (4. 'C'). getchar (). destino: char). 2. char b. Transfira n-1 discos da torre B para torre C. } } main (void) { hanoi (4. origem.

página 30 . aplicar novamente a solução de três discos.Lázaro 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. movendo-os de B para C. verificamos que uma solução recursiva é o método mais natural e lógico de solucionar um problema. sabemos como deslocar os quatro primeiros discos da torre A para a torre B usando C como auxiliar. aplicar novamente a solução para dois discos. por último. do que uma versão recursiva. ocorre um conflito entre a eficiência da máquina e a do programador. Em geral. usando a torre A como auxiliar.Estrutura de Dados 2 . uma versão não-recursiva de um programa executará com mais eficiência. não compensa para o programador construir exaustivamente uma solução nãorecursiva (Tenenbaum. Perceba a recursividade nos parágrafos acima. deslocarmos o disco 2 da torre B e deslocarmos o disco 1 para a torre B em cima do disco 2. usando a torre A como auxiliar. movendo-os de C para B. Dessa forma. chegamos ao ponto em que. aplicar novamente a solução aos quatro discos. Com o custo da programação aumentando consideravelmente e o custo da computação diminuindo. Contudo. movendo-os de B para C usando A como auxiliar. na maioria dos casos. Isso acontece porque o trabalho extra dispendido para entrar e sair de um bloco é evitado na versão não-recursiva. Como parágrafo acima. Cada parágrafo caracteriza as instruções da rotina conforme programa apresentado. em termos de tempo e espaço. sabemos como deslocar os três primeiros discos da torre A para a torre C usando B como auxiliar. Poderíamos deslocar o maior disco de A para C e. Poderíamos deslocar o disco 3 da torre A para a torre C e. Como parágrafo acima. 2005). Poderíamos deslocar o quarto disco da torre A para a torre B e.

Representação esquemática: b a c d e f g Terminologia: h i j k A raiz desta árvore é o nó a. o nível dos nós e quais são os nós folha e raiz. O demais níveis são definidos pelo número de ramos que o ligam com o nó raiz. O nível do nó raiz é zero. é a estrutura indicada para aplicações onde é necessário representar ordem e hierarquia. Exercício: Para a árvore anterior encontre o grau. Mas todo nó é a raiz de uma subárvore. Então a tem grau 2. O número de subárvores de um nó é o grau daquele nó. por exemplo. Então b é a raiz de uma subárvore que tem dois nós d e e. O nó e. d é a raiz de uma subárvore vazia. Um nó de grau zero é um nó folha ou nó terminal.Estrutura de Dados 2 . Devido a isto.Lázaro Eduardo da Silva 6 Árvore A árvore é uma estrutura de dados que caracteriza a hierarquia entre seus dados. Floresta é um conjunto de duas ou mais árvores. tem nível 2. Então d é uma folha desta árvore. nó a b c d e f g h i j k Grau nível observação página 31 .

onde o grau de cada nó é menor ou igual a dois.1. Então para o exemplo anterior de árvore binária. a subárvore direita do nó a começa com o nó c e a subárvore esquerda começa com o nó b.Estrutura de Dados 2 . b. e. c. distinção entre a subárvore direita e esquerda. a página 32 .1 Árvore Binária São estruturas do tipo árvore. Caminhamento central (em-ordem) • Percorrer a subárvore esquerda • Processar o nó • Percorrer a subárvore direita 3.1 Caminhamento em Árvore Binária Caminhar em uma árvore binária significa percorrer todos os nós da árvore de forma sistemática de modo que cada nó seja visitado uma única vez. 6. f pós-ordem: d. c. f. b. d. Caminhamento pré-fixado (pré-ordem) • Processar o nó • Percorrer a subárvore esquerda • Percorrer a subárvore direita 2. a. e. Exemplo: a b c d e f Existe numa árvore binária. Existem 3 formas básicas de caminhamento em árvore binária: 1. Caso contrário dizemos que é uma árvore orientada. dizemos que a árvore é ordenada. e. 6.Lázaro Eduardo da Silva Quando a ordem das subárvores é relevante. c. b. f em-ordem: d. Caminhamento pós-fixado (pós-ordem) • Percorrer a subárvore esquerda • Percorrer a subárvore direita • Processar o nó Exemplo: Os nós da árvore binária anterior são processados da seguinte forma segundo cada caminhamento: pré-ordem: a.

e . . em-ordem e pós-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.f. 2..1.Estrutura de Dados 2 . e . a b d . Suponha que os elementos da árvore aparecem em pré-ordem e que um ponto representa uma subárvore vazia.Lázaro Eduardo da Silva Exercício: Escreva quais são os resultados dos caminhamentos pré-ordem. .de. página 33 . representa a seguinte árvore binária: a b g c d e f Exercícios: Represente as árvores correspondentes às seguintes seqüências: 1... c d .c. .. c . . . . Assim a seqüência abg. a b .2 Construção de Árvore Binária: Usaremos uma forma seqüencial dos nós para facilitar o processo de construção de uma árvore binária.

Inserção em Árvore Binária: A inserção dos valores 4. 2. 4. Exemplo: 4 2 1 3 5 7 Nó a remover 1 2 3 4 5 Caso 2: Nenhuma das subárvores do nó é vazia. Remoção e Consulta ordenada em Árvore Binária: A estrutura de árvore binária é indicada para manutenção ordenada de dados. O valor 1 que é menor que 2 está à esquerda de 2. O símbolo seguinte pode ser. Escreva a seqüência em pré-ordem de construção da seguinte árvore binária: A) a b c B) a b d d e c e f g f 6. . por exemplo.3 Inserção. os valores maiores que 4 (5.b . 4. 7 e 8. . 7. a árvore quando percorrida em-ordem terá todos os seus dados ordenados. 1. Assim. se usarmos o critério que dados maiores devem ser inseridos no ramo direito e que os dados menores devem ser inseridos no ramo esquerdo. Neste caso o nó a ser removido deve ser substituído pelo símbolo seguinte na ordem a qual a árvore está organizada. 5 e 8 usando o critério citado anteriormente dá como resultado a seguinte árvore binária: 4 2 1 3 5 7 8 Esta árvore percorrida em-ordem dá como resultado estes dados ordenados: 1.7 e 8) estão à direita. a . 3. o página 34 . 5.Estrutura de Dados 2 . 3. Assim. Remoção da Árvore Binária: Para remover um nó de uma árvore temos que analisar dois casos: Caso 1: O nó a ser removido possui uma ou ambas subárvores vazias. . c . Neste caso a remoção é feita com a ligação do subramo esquerdo ou direito com o próximo nó. a b c .1. 2. Observe que para toda subárvore temos os dados maiores que o nó raiz à direita e os dados menores que o nó raiz à esquerda.Lázaro Eduardo da Silva 3. .

compara-se 3 com a raiz (4). end. constroi (a^.esq). constroi (a^.dir). a^. dispose (a).esq).dir). ou seja. por exemplo. 3 é menor que 4. type arvore = ^no. no = record esq : arvore. Exemplo: Nó a remover 2 1 3 5 4 7 8 1 2 3 5 7 8 Consulta da Árvore Binária: Para procurar um nó na árvore basta acompanhar a ordenação dos elementos em relação ao valor procurado. end. uses crt. var c: char. begin c := readkey. aquele que contém o menor valor da subárvore direita do nó a ser removido. write (c). begin if a <> nil then begin destroi (a^. Então. dir : arvore. Esta verificação acontece até que o valor procurado seja encontrado ou que seja alcançada uma subárvore vazia. para procurar o valor 3 na árvore binária ordenada anterior. info : char.Lázaro Eduardo da Silva menor dos maiores. op : integer. Programa Exemplo em Pascal: program Arvore_Binaria. var a : arvore.Estrutura de Dados 2 . página 35 . destroi (a^.info := c. logo o valor 3 se estiver presente na árvore binária estará na subárvore esquerda do nó 4.' then a := nil else begin new (a). car: char. procedure destroi (var a : arvore). a := nil. end. if c = '. procedure constroi (var a : arvore).

begin if a <> nil then begin if c > a^. function inter (p : arvore) : arvore. c) else insere (a^. end.s : arvore. var r. a^. if c < p^. c : char). while r <> nil do begin s := r.info then insere (a^. end.esq else p := p^.dir. end.Estrutura de Dados 2 .esq.info then p := p^. a^. while (p^. end else begin if p^. a^.info <> c) and (p <> nil) do begin q := p.esq := nil. c : char). begin r := p^. q := nil. var p.dir := nil.dir. q : arvore.esq. end. c). end. inter := s.info := c.esq = nil then begin if q = nil then a := p^. procedure insere (var a : arvore. s := r.Lázaro Eduardo da Silva end.dir else página 36 . end else begin new (a).dir. if p = nil then begin writeln ('No nao encontrado'). r := r^. procedure retira (var a : arvore. end. begin p := a.

begin if a <> nil then begin write (a^.info). página 37 . dispose (p).info := q^.esq). em_ordem (a^.info.esq = p then q^. dispose (p). p^.Lázaro Eduardo da Silva begin if q^. end.dir. pre_ordem (a^.esq else q^.dir else q^. retira (p^.esq = p then q^.dir).info). procedure em_ordem (a : arvore).esq := p^. end end. write (a^.Estrutura de Dados 2 . end. end.dir. procedure pos_ordem (a : arvore).esq. pre_ordem (a^. end end else begin q := inter (p).esq). q^.esq else begin if q^. end end. begin if a <> nil then begin em_ordem (a^.info). procedure pre_ordem (a : arvore).dir).esq := p^. end.dir = nil then begin if q = nil then a := p^.dir := p^. begin if a <> nil then begin pos_ordem (a^.esq). end end else begin if p^.dir := p^.

begin write('Digite uma sequencia (ex: ab. em_ordem (a). insere (a.: '). insere (a.h> #include <string. '4'). em_ordem (a). '3'). }. em_ordem (a). insere (a. insere (a.info).Estrutura de Dados 2 . struct arv *dir. constroi (a). destroi (a). em_ordem (a). write ('Pos-ordem: '). pre_ordem (a). writeln..: ').h> struct arv { char info[30].): '). writeln. end end. void preordem (struct arv *no). Programa Exemplo em C: #include <stdio. '4'). writeln. write ('Pre-ordem: '). '1'). insere (a. void posordem (struct arv *no). retira (a.: '). insere (a. end. write ('Em ordem. writeln. write ('Em ordem. write (a^.dir).. '8').: '). '5').. write ('Em ordem.Lázaro Eduardo da Silva pos_ordem (a^. retira (a.e. write ('Em-ordem. '1'). pos_ordem (a). readln. insere (a. struct arv *constroi (void). '2'). página 38 . writeln.cd. struct arv *esq. '7'). writeln.h> #include <stdlib..

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

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

Lázaro Eduardo da Silva ordeminter (struct arv *no) { if (no) { ordeminter (no->esq). ordeminter (no->dir). i++) printf (" "). for (i = 0. } } void destroi (struct arv *no) { if (no) { destroi (no->esq).Estrutura de Dados 2 . no = NULL. } } void mostra (struct arv *no. if (no) { mostra (no->dir. puts (no->info). mostra (no->esq. puts (no->info). nivel + 1). nivel + 1). free (no). i < nivel. int nivel) { int i. destroi (no->dir). } } página 41 .

• Classificação por Seleção: Espalhe as cartas na mesa.MAX] of integer. end. Existem 3 métodos gerais para classificação interna de dados: • classificação por troca • classificação por seleção • classificação por inserção Para entender estes métodos suponha o problema de ordenação das cartas do baralho. Programa exemplo Pascal: program ordena_por_troca. Ponha uma carta por vez na mesa. trocando-os de posição caso estejam fora da ordem desejada.1 Classificação por Troca Estes métodos caracterizam-se por efetuarem a classificação por comparação sucessiva de pares de elementos. retire-a do baralho e segure-a na sua mão. troca := true. O processo de classificação de um conjunto de dados inteiramente contido na memória primária é chamado de classificação interna. for i := 1 to MAX do begin vetor[i] := random (100).Lázaro Eduardo da Silva 7 Métodos de Classificação Classificação ou ordenação de dados é uma das tarefas mais freqüentes e importantes em processamento de dados. • Classificação por troca: Espalhe as cartas numa mesa voltadas para cima e então troque as cartas de ordem até que todo o baralho esteja ordenado. ') else writeln (vetor[i]. • Classificação por Inserção: Segure todas as cartas na sua mão. i. var vetor: array [1. begin randomize. sempre inserindo na posição correta. const MAX = 20.'). while troca do begin troca := false. O maço estará ordenado quando não restarem mais cartas em sua mão. writeln ('ORDENACAO POR TROCA'). writeln ('Antes da Ordenacao').Estrutura de Dados 2 . A importância da classificação de dados pode ser avaliada se considerarmos o que seria o problema de localização do nome de um assinante em uma lista telefônica. if (i < MAX) then write (vetor[i]. writeln ('------------------'). selecione a carta de menor valor. troca: boolean.. '. salva: integer. ao passo que a classificação de um conjunto de dados não inteiramente armazenado na memória primária é chamada de classificação externa. 7. na qual os nomes não estivessem em ordem alfabética. '. página 42 . Este processo continua até que todas as cartas estejam na sua mão.

end.h> #include <stdlib. salva. vetor[i+1] = salva. end. bool troca.vetor[i]). vetor[i] = vetor[i+1].'). vetor[i] := vetor[i+1]. while (troca) { troca = false.\n". Programa exemplo C: #include <stdio. troca := true. } } } página 43 . vetor[i+1] := salva. printf("ORDENACAO POR TROCA\n\n"). i.Lázaro Eduardo da Silva for i := 1 to MAX-1 do begin if (vetor[i] > vetor[i+1]) then begin salva := vetor[i]. writeln ('Depois da Ordenacao').h> #include <string. printf("-------------------\n"). readln.h> #define MAX 20 int main() { int vetor[MAX]. ') else writeln (vetor[i].vetor[i]). if(i<(MAX-1)) printf("%d. else printf("%d. ".'.i++) { if (vetor[i] > vetor[i+1]) { salva = vetor[i].Estrutura de Dados 2 . '.i<(MAX-1). printf("Antes da Ordenacao\n").i<MAX. troca = true. } troca=true. end. for i := 1 to MAX do if (i < MAX) then write (vetor[i]. end. for(i=0. for (i=0. writeln ('-------------------').i++) { vetor[i]=rand()%100.

a classificação é efetivada por seleção sucessiva do menor valor dentro do vetor. for i := 1 to MAX-1 do begin menor := i.73. '. system("pause"). for i := 1 to MAX do begin vetor[i] := random (100).46. var vetor: array [1. menor. ". writeln ('Antes da Ordenacao').MAX] of integer.vetor[i]).29. salva: integer.2> a seqüência de passos que será executado por este método para ordenação 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 ordenação é como se os valores menores fossem as bolhas flutuando para ocupar as primeiras posições no vetor. ') else writeln (vetor[i].i++) if (i < (MAX-1)) printf ("%d.2 Classificação por Seleção Nestes métodos. Programa exemplo em Pascal: program ordena_por_selecao. i.vetor[i]). página 44 .11. else printf ("%d. } Para o vetor <50.\n\n".22. writeln ('ORDENACAO POR SELECAO'). writeln ('------------------'). const MAX = 20.Lázaro Eduardo da Silva printf ("\nDepois da Ordenacao\n"). 7. for (i=0.Estrutura de Dados 2 . printf ("-------------------\n").. j. if (i < MAX) then write (vetor[i].91.').89. '. end. begin randomize.i<MAX. A cada passo o elemento de menor valor é colocado em sua posição definitiva no vetor classificado e o processo é repetido para o segmento que contém os elementos ainda não selecionados.54.

else printf("%d. '. salva.vetor[i]). j.i<MAX.vetor[i]). vetor[menor] = salva. salva := vetor[i]. printf("ORDENACAO POR SELECAO\n\n"). system("pause"). if(i<(MAX-1)) printf("%d. ".Lázaro Eduardo da Silva for j := i+1 to MAX do if (vetor[j] < vetor[menor]) then menor := j. menor. for(j=i+1.i++) { vetor[i]=rand()%100. end. else printf ("%d.'. i. Programa exemplo em C: #include <stdio.vetor[i]). ') else writeln (vetor[i]. writeln ('Depois da Ordenacao').h> #include <stdlib. readln.i<MAX-1. printf ("-------------------\n").vetor[i]).h> #include <string.h> #define MAX 20 int main() { int vetor[MAX]. } for(i=0. } printf ("\nDepois da Ordenacao\n"). vetor[i] = vetor[menor].j<MAX. writeln ('-------------------'). salva = vetor[i]. end. } página 45 .i<MAX. printf("Antes da Ordenacao\n"). ".Estrutura de Dados 2 . for i := 1 to MAX do if (i < MAX) then write (vetor[i]. for(i=0.\n".j++) if (vetor[j] < vetor[menor]) menor = j.\n\n". vetor[menor] := salva. vetor[i] := vetor[menor].i++) { menor = i. for (i=0. printf("-------------------\n").').i++) if (i < (MAX-1)) printf ("%d.

i := 2. '.75. end. while x < vetor[j] do begin vetor[j+1] := vetor[j]. end.51. writeln ('ORDENACAO POR INSERCAO'). const MAX = 20. i := i+1.36. ') else writeln (vetor[i].46.MAX] of integer. for i := 1 to MAX do begin vetor[i] := random (100). vetor[j+1] := x. salva: integer. writeln ('------------------'). while i <= MAX do begin x := vetor[i].20. '. writeln ('-------------------'). x. j := j-1.78. vetor[0] := vetor[i].17. writeln ('Depois da Ordenacao'). j. end. for i := 1 to MAX do if (i < MAX) página 46 .. if (i < MAX) then write (vetor[i]. i. begin randomize.Estrutura de Dados 2 .').60. Programa exemplo em Pascal: program ordena_por_insercao. var vetor: array [0.3 Classificação por Inserção A característica comum de todos os métodos de classificação por inserção é que eles efetivam a ordenação do vetor pela inserção de cada um dos elementos em sua posição dentro de um subvetor classificado. j := i-1.Lázaro Eduardo da Silva Para o vetor <52. writeln ('Antes da Ordenacao').80> a seqüência de passos que será executado por este método para ordenação 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.

Lázaro Eduardo da Silva then write (vetor[i].vetor[i]). else printf ("%d. while (i < MAX) { x = vetor[i].vetor[i]). } vetor[j+1] = x. salva. j = i-1.h> #include <string.vetor[i]).i++) if (i < MAX) printf ("%d.80.71. end.12. else printf("%d. for(i=1. vetor[0] = vetor[i]. } printf ("\nDepois da Ordenacao\n").\n".Estrutura de Dados 2 .').\n\n". j. ".30.46.36. } Para o vetor <33. printf("Antes da Ordenacao\n"). printf("-------------------\n"). printf("ORDENACAO POR SELECAO\n\n").i++) { vetor[i]=rand()%100. x.vetor[i]).94.i<=MAX. Programa exemplo em C: #include <stdio. printf ("-------------------\n"). ') else writeln (vetor[i].h> #include <stdlib.i<=MAX. if(i<MAX) printf("%d.69. readln. i. while (x < vetor[j]) { vetor[j+1] = vetor[j]. system("pause"). i = i+1. '. j = j-1. ". } i = 2.h> #define MAX 20 int main() { int vetor[MAX].'.74> a seqüência de passos que será executado por este método para ordenação 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 página 47 . for (i=1.

Escreva um programa que utilize esta função. 2.Estrutura de Dados 2 . página 48 . Experimente inserir valores inversos e verifique qual é o melhor algoritmo de classificação para esta situação. Para julgar a eficiência dos algoritmos utilize a função implementada na questão anterior. Implemente uma função que conte o número de trocas necessárias para cada algoritmo de classificação.Lázaro Eduardo da Silva 12 12 12 12 12 12 Exercícios: 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.

. São Paulo. J.D. AZEREDO. S. PAULO e FURTADO. 2005.. A.Algorithms + Data Structures = Programs. 1999.V. USA.icmc. LTC. E. YEDIDYAH.. 1996. Prentice Hall. 1986. 4a Ed. 1994. Makron Books. and SAHNI. PAULO. São Paulo. São Paulo.. Projeto de Algoritmos: com implementações em Pascal e C.Estrutura de Dados Fundamentais: conceitos e aplicações.. The art of computer programming. Calif. 1997. Addison-Wesley. AARON M. 1993. PEREIRA. Graça. TENENBAUM. WIRTH.Estrutura de Dados: conceitos e técnicas de implementação. . N. Textos Clássicos: HOROWITZ. JAYME LUIZ .Estrutura de Dados. vol 1 – Fundamental algorithms. Material didático da disciplina Algoritmos e Estruturas de Dados. MOSHE J. D. and ULMAN J.br/~sce182/. Rio de Janeiro.. HOPCROFT. MARCOS VIANA . – Estrutura de Dados usando C. AHO. 1983. página 49 .Lázaro Eduardo da Silva 8 Bibliografia KNUTH. VELOSO. Disponível em http://www.. Computer Science Press.Estrutura de Dados 2 . ANTÔNIO . LANGSAM. N.Estrutura de Dados e seus algoritmos.E. AUGENSTEIN.usp. PIMENTEL.E. SANTOS. Addison Wesley.J. SZWARCFITER.Data Structures and Algorithms. Pioneira. 1976. ZIVIANI.. . Campus. Rio de Janeiro. Mass. Érica. N. . 1975. CLÉSIO DOS. SÍLVIO DO LAGO .Fundamentals of Data Structures. Campus. VILLAS. Rio de Janeiro.

Sign up to vote on this title
UsefulNot useful