P. 1
Apostila Estrutura de Dados

Apostila Estrutura de Dados

|Views: 1.603|Likes:
Publicado porJorge Azevedo

More info:

Published by: Jorge Azevedo on Jan 17, 2012
Direitos Autorais:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

05/14/2013

pdf

text

original

Sections

  • 2 Tipo Apontador (Ponteiro)
  • 2.1 Ponteiros
  • 2.1.1 Declaração:
  • 2.1.2 Inicialização:
  • 2.1.3 Criação de uma variável dinâmica:
  • 2.1.4 Destruição de uma variável dinâmica:
  • 2.1.5 Referência a uma variável dinâmica:
  • 3 Pilhas e Filas
  • 3.1 Pilha
  • 3.1.1 Implementação de Pilha usando Alocação Dinâmica de Memória
  • 3.2 Fila
  • 3.2.1 Implementação de Fila usando Alocação Dinâmica de Memória
  • 4 Listas Lineares
  • 4.1 Listas Lineares por Encadeamento
  • 4.1.1 Lista Linear Encadeada usando Vetor:
  • 4.1.2 Lista Encadeada usando Alocação Dinâmica de Memória
  • 5 Recursividade
  • 5.1 O problema das Torres de Hanoi
  • 6 Árvore
  • 6.1.1 Caminhamento em Árvore Binária
  • 6.1.2 Construção de Árvore Binária:
  • 6.1.3 Inserção, Remoção e Consulta ordenada em Árvore Binária:
  • 7.1 Classificação por Troca
  • 8 Bibliografia

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

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

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

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

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

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

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

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

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

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

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

Cada elemento indica qual é o elemento que vem em seguida através do valor no campo lig. página 15 . e o campo lig (ligação) utilizado para prover o encadeamento 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.Estrutura de Dados 2 . e o começo da lista propriamente dita está indicado na variável com. O valor -1 marca o fim da lista.1. 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.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.Lázaro Eduardo da Silva 4. O começo da lista de posições disponíveis da estrutura está indicada na variável dispo.

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

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

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

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

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

lig : lista. página 21 .c. limitação do tamanho da lista. s: string). y). char nome. } Exercícios: 1. d.d).1. case '2' : printf("Remover"). do { system("cls"). &c.Estrutura de Dados 2 . end. break. 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. o = leopcao(). end. Escreva um programa que utilize esta função. Programa Exemplo em Pascal: program lista_encadeada_por_alocacao. &d. retiralista(L. type lista = ^no. } }while (o != '3'). y: integer. break. Com o recurso de alocação dinâmica de memória conseguimos resolver o primeiro problema. procedure escxy (x. Escreva uma função que busque um valor em uma lista encadeada e informe em que posição este valor está. 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. switch (o) { case '1' : printf("Inserir"). &d. &nome). &d). representa (L. &nome). inicialista (L. inserelista (L. &c. &c.Lázaro Eduardo da Silva return (val). } main () { struct no L[MAX]. Escreva uma função que concatena duas listas encadeadas. no = record info : string. Escreva um programa que utilize esta função. char o. ou seja. 2. nome=lenome(). write (s). int c. nome=lenome(). uses crt. 4.

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

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

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

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

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

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

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

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

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

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

Caminhamento central (em-ordem) • Percorrer a subárvore esquerda • Processar o nó • Percorrer a subárvore direita 3. Então para o exemplo anterior de árvore binária. b. dizemos que a árvore é ordenada. c. 6.1 Árvore Binária São estruturas do tipo árvore. c. Caminhamento pré-fixado (pré-ordem) • Processar o nó • Percorrer a subárvore esquerda • Percorrer a subárvore direita 2. b.1. e. distinção entre a subárvore direita e esquerda. a. d. f. Existem 3 formas básicas de caminhamento em árvore binária: 1. a página 32 . Caso contrário dizemos que é uma árvore orientada. 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. f em-ordem: d. c. 6.Estrutura de Dados 2 . e. f pós-ordem: d. a subárvore direita do nó a começa com o nó c e a subárvore esquerda começa com o nó b.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. b. onde o grau de cada nó é menor ou igual a dois. Exemplo: a b c d e f Existe numa árvore binária.Lázaro Eduardo da Silva Quando a ordem das subárvores é relevante.

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

1.7 e 8) estão à direita. . 1. c . 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. 7 e 8.3 Inserção. 2. . 7. O valor 1 que é menor que 2 está à esquerda de 2. a . Remoção e Consulta ordenada em Árvore Binária: A estrutura de árvore binária é indicada para manutenção ordenada de dados.b . 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. 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. 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. 3. por exemplo. Exemplo: 4 2 1 3 5 7 Nó a remover 1 2 3 4 5 Caso 2: Nenhuma das subárvores do nó é vazia.Estrutura de Dados 2 . O símbolo seguinte pode ser. a b c . Assim. Inserção em Árvore Binária: A inserção dos valores 4. Assim. . 5. 3. 4. os valores maiores que 4 (5. a árvore quando percorrida em-ordem terá todos os seus dados ordenados. Observe que para toda subárvore temos os dados maiores que o nó raiz à direita e os dados menores que o nó raiz à esquerda. 4. Neste caso a remoção é feita com a ligação do subramo esquerdo ou direito com o próximo nó. 2.Lázaro Eduardo da Silva 3. . Neste caso o nó a ser removido deve ser substituído pelo símbolo seguinte na ordem a qual a árvore está organizada. o página 34 .

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

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

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

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

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

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

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

salva: integer. troca: boolean. 7. begin randomize. Ponha uma carta por vez na mesa. • 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. Programa exemplo Pascal: program ordena_por_troca.').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.Estrutura de Dados 2 . end. Este processo continua até que todas as cartas estejam na sua mão. const MAX = 20. página 42 .MAX] of integer. na qual os nomes não estivessem em ordem alfabética. writeln ('ORDENACAO POR TROCA'). • Classificação por Seleção: Espalhe as cartas na mesa. if (i < MAX) then write (vetor[i]. trocando-os de posição caso estejam fora da ordem desejada. 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. sempre inserindo na posição correta. i.1 Classificação por Troca Estes métodos caracterizam-se por efetuarem a classificação por comparação sucessiva de pares de elementos. selecione a carta de menor valor. '. '. O maço estará ordenado quando não restarem mais cartas em sua mão. writeln ('------------------'). troca := true. var vetor: array [1. 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. while troca do begin troca := false. 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. retire-a do baralho e segure-a na sua mão.. • Classificação por Inserção: Segure todas as cartas na sua mão. for i := 1 to MAX do begin vetor[i] := random (100). writeln ('Antes da Ordenacao'). O processo de classificação de um conjunto de dados inteiramente contido na memória primária é chamado de classificação interna. ') else writeln (vetor[i].

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

a classificação é efetivada por seleção sucessiva do menor valor dentro do vetor.73. Programa exemplo em Pascal: program ordena_por_selecao..Estrutura de Dados 2 .46. var vetor: array [1. ') else writeln (vetor[i].i++) if (i < (MAX-1)) printf ("%d. '. writeln ('ORDENACAO POR SELECAO'). end. i. salva: integer. else printf ("%d. const MAX = 20. ".vetor[i]). begin randomize.91.2 Classificação por Seleção Nestes métodos. 7.\n\n".54.89.22. } Para o vetor <50.vetor[i]). for i := 1 to MAX-1 do begin menor := i.Lázaro Eduardo da Silva printf ("\nDepois da Ordenacao\n"). página 44 .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. system("pause"). writeln ('Antes da Ordenacao').i<MAX.11. '.29. menor. writeln ('------------------'). for i := 1 to MAX do begin vetor[i] := random (100).'). for (i=0. j.MAX] of integer. if (i < MAX) then write (vetor[i]. printf ("-------------------\n"). 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.

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

60.'). end. Programa exemplo em Pascal: program ordena_por_insercao. var vetor: array [0.75.17. while i <= MAX do begin x := vetor[i]. '. while x < vetor[j] do begin vetor[j+1] := vetor[j]. j := i-1. begin randomize.20. if (i < MAX) then write (vetor[i].MAX] of integer. for i := 1 to MAX do if (i < MAX) página 46 . i := i+1. writeln ('ORDENACAO POR INSERCAO'). i := 2..Lázaro Eduardo da Silva Para o vetor <52. const MAX = 20.46.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. ') else writeln (vetor[i]. salva: integer. writeln ('------------------'). x.51. '.Estrutura de Dados 2 . for i := 1 to MAX do begin vetor[i] := random (100). writeln ('Antes da Ordenacao'). j.36. end. end.78. i. writeln ('-------------------'). j := j-1. vetor[j+1] := x.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. vetor[0] := vetor[i]. writeln ('Depois da Ordenacao').

i<=MAX.Lázaro Eduardo da Silva then write (vetor[i]. for(i=1.30.71. } Para o vetor <33. ".12. j.36. while (x < vetor[j]) { vetor[j+1] = vetor[j].Estrutura de Dados 2 .94. while (i < MAX) { x = vetor[i]. vetor[0] = vetor[i].\n\n".i<=MAX.vetor[i]). } printf ("\nDepois da Ordenacao\n").vetor[i]). ". '.69.vetor[i]). printf("ORDENACAO POR SELECAO\n\n").h> #include <string. salva. printf("Antes da Ordenacao\n").vetor[i]).h> #define MAX 20 int main() { int vetor[MAX].').46.\n". for (i=1. i. system("pause").i++) { vetor[i]=rand()%100. ') else writeln (vetor[i]. x. } i = 2. else printf ("%d. if(i<MAX) printf("%d. i = i+1. j = j-1. Programa exemplo em C: #include <stdio. end.h> #include <stdlib.'.i++) if (i < MAX) printf ("%d. printf ("-------------------\n"). j = i-1. } vetor[j+1] = x.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 .80. readln. printf("-------------------\n"). else printf("%d.

Estrutura de Dados 2 . Escreva um programa que utilize esta função. página 48 . 2.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. 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.

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

You're Reading a Free Preview

Descarregar
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->