Sei sulla pagina 1di 108

Estrutura de Dados

v1.1 2012A

Sumrio
1. 2. Introduo ............................................................................................................................................................ 4 Tipos de Dados ..................................................................................................................................................... 5

2.1 Primitivos, Estticos e Dinmicos ......................................................................................................................... 5 3. Variveis ............................................................................................................................................................... 6

3.1 Variveis Compostas Homogneas........................................................................................................................ 6 3.1.1 Variveis Compostas unidimensionais............................................................................................................... 6 3.1.2 Variveis Compostas multidimensionais............................................................................................................ 6 3.2 Variveis Compostas Heterogneas ...................................................................................................................... 6 3.2.1 Registros............................................................................................................................................................. 6 3.2.2 Conjunto de Registros ........................................................................................................................................ 6 4. Listas Lineares ..................................................................................................................................................... 7

4.1 Motivao .............................................................................................................................................................. 7 4.2 Conceituao ......................................................................................................................................................... 7 4.3 Operaes .............................................................................................................................................................. 7 4.4 Classificao.......................................................................................................................................................... 8 4.5 Representaes ...................................................................................................................................................... 8 4.5.1 Contigidade ...................................................................................................................................................... 8 4.5.2 Encadeamento .................................................................................................................................................... 9 4.5.3 Tipo Apontador (Ponteiro) ............................................................................................................................... 10 4.5.4 Uso da Memria ............................................................................................................................................... 10 5. Listas Lineares Seqenciais .............................................................................................................................. 12

5.1 Representao Genrica...................................................................................................................................... 12 5.2 Caractersticas: ................................................................................................................................................... 12 5.3 Vantagens ............................................................................................................................................................ 12 5.4 Desvantagens ....................................................................................................................................................... 12 5.5 Implementaes ................................................................................................................................................... 13 5.5.1 Lista K.............................................................................................................................................................. 13 5.5.2 Lista Operaes ................................................................................................................................................ 16 6. Listas Lineares com Disciplina de Acesso ........................................................................................................ 21

6.1 Pilhas ................................................................................................................................................................... 21 6.1.1 Definio .......................................................................................................................................................... 21 6.1.2 Aplicao.......................................................................................................................................................... 22 6.1.3 Operaes Bsicas............................................................................................................................................ 22 6.1.4 Implementao de Pilha com Lista Seqencial ................................................................................................ 23 6.2 Filas ..................................................................................................................................................................... 26 6.2.1 Definio .......................................................................................................................................................... 26 6.2.2 Aplicao.......................................................................................................................................................... 26 6.2.3 Operaes Bsicas............................................................................................................................................ 26 6.2.4 Implementao de Fila com Lista Seqencial .................................................................................................. 27 7. Implementaes por Encadeamento................................................................................................................. 30

7.1 Lista Simplesmente Encadeada............................................................................................................................ 30 7.1.1 Definio .......................................................................................................................................................... 30 7.1.2 Aplicao.......................................................................................................................................................... 30 7.1.3 Componente da Lista........................................................................................................................................ 30 7.1.4 Esquema da Representao .............................................................................................................................. 30 7.1.5 Operaes Bsicas............................................................................................................................................ 31

7.1.6 Implementao Lista Simplesmente Encadeada............................................................................................... 31 7.2 Lista Simplesmente Encadeada com Descritor.................................................................................................... 37 7.2.1 Implementao Lista Simplesmente Encadeada com Descritor ....................................................................... 38 7.3 Lista Circular Encadeada.................................................................................................................................... 45 7.3.1 Definio .......................................................................................................................................................... 45 7.3.2 Implementao Lista Encadeada Circular ........................................................................................................ 45 7.4 Lista Duplamente Encadeada .............................................................................................................................. 50 7.4.1 Definio .......................................................................................................................................................... 50 7.4.2 Aplicao.......................................................................................................................................................... 50 7.4.3 Componente da Lista........................................................................................................................................ 50 7.4.4 Esquema da Representao .............................................................................................................................. 50 7.4.5 Implementao Lista Duplamente Encadeada.................................................................................................. 51 7.5 Lista Duplamente Encadeada com Descritor ...................................................................................................... 57 7.5.1 Implementao Lista Duplamente Encadeada com Descritor .......................................................................... 57 7.6 Listas Encadeadas com Disciplina de Acesso ..................................................................................................... 64 7.6.1 Pilha com Encadeamento ................................................................................................................................. 64 7.6.2 Implementao de Pilha com Encadeamento ................................................................................................... 64 7.6.3 Fila com Encadeamento ................................................................................................................................... 66 7.6.4 Implementao de Fila com Encadeamento ..................................................................................................... 67 8. Recursividade ..................................................................................................................................................... 70

8.1 Introduo............................................................................................................................................................ 70 8.2 Como codificar programas recursivos ................................................................................................................ 70 8.3 Quando no se deve empregar recurso ............................................................................................................. 72 8.4 Vantagens X Desvantagens de um programa recursivo em relao a um programa iterativo............................ 74 8.5 Mais dois exemplos de programas recursivos ..................................................................................................... 75 8.5.1 Exemplo 1 ........................................................................................................................................................ 75 8.5.2 Exemplo 2 ........................................................................................................................................................ 75 9. rvores................................................................................................................................................................ 79

9.1 Introduo............................................................................................................................................................ 79 9.2 Terminologia........................................................................................................................................................ 79 9.3 Representaes Bsicas para rvores ................................................................................................................. 81 9.3.1 Diagrama de Incluso....................................................................................................................................... 81 9.3.2 Representao Hierrquica............................................................................................................................... 81 9.3.3 Diagrama de Barras.......................................................................................................................................... 82 9.3.4 Parntesis Aninhados ....................................................................................................................................... 82 9.3.5 Representao Matricial ................................................................................................................................... 82 9.4 rvore Binria ..................................................................................................................................................... 82 9.4.1 Tipos de rvores Binrias ................................................................................................................................ 83 9.4.2 Caminhamento em rvore Binria................................................................................................................... 84 9.4.3 Inserindo dados em uma rvore Binria.......................................................................................................... 86 9.4.4 Aplicaes de rvores Binrias ....................................................................................................................... 86 9.5 Alocao .............................................................................................................................................................. 87 9.5.1 Alocao com Contigidade ............................................................................................................................ 87 9.5.2 Alocao com Encadeamento........................................................................................................................... 88 9.6 Implementao rvore Binria............................................................................................................................ 89 9.6.1 Implementao Recursiva de rvores Binrias de Busca ................................................................................ 90 9.6.2 Implementao Iterativa de rvores Binrias de Busca................................................................................... 93 9.7 rvores B ............................................................................................................................................................. 98 9.7.1 Definio .......................................................................................................................................................... 98 9.7.2 Estrutura do N ................................................................................................................................................ 98

9.8 rvores B+........................................................................................................................................................... 99 10. Clculo de Endereo ........................................................................................................................................ 100 10.1 Introduo.......................................................................................................................................................... 100 10.2 Vantagens e Desvantagens ................................................................................................................................ 101 10.3 Funes Hash .................................................................................................................................................... 101 10.3.1 Mtodo da Diviso ......................................................................................................................................... 101 10.3.2 Mtodo da Dobra............................................................................................................................................ 102 10.3.3 Mtodo da Multiplicao................................................................................................................................ 103 10.4 Tratamento de Colises ..................................................................................................................................... 104 10.4.1 Hashing com Tentativas Lineares .................................................................................................................. 104 10.4.2 Hashing Duplo................................................................................................................................................ 104 10.4.3 Hashing Quadrtico........................................................................................................................................ 105 10.4.4 Hashing com Encadeamento .......................................................................................................................... 105 11. Bibliografia ....................................................................................................................................................... 107

1. Introduo
A automatizao de tarefas um aspecto marcante da sociedade moderna e na cincia da computao houve um processo de desenvolvimento simultneo e interativo de mquinas (hardware) e dos elementos que gerenciam a execuo automtica (software) de uma tarefa. Nesta grande evoluo do mundo computacional, um fator de relevante importncia a forma de armazenar as informaes, j que, informtica a cincia da informao. Ento de nada adiantaria o grande desenvolvimento do hardware e do software, se a forma de armazenamento e tratamento da informao no acompanhasse esse desenvolvimento. Por isso a importncia das estruturas de dados, que nada mais so que formas otimizadas de armazenamento e tratamento das informaes eletronicamente. As estruturas de dados, na sua maioria dos casos, foram espelhadas em formas naturais de armazenamento do nosso dia a dia, ou seja, nada mais so que a transformao de uma forma de armazenamento j conhecida e utilizada no nosso mundo para o mundo computacional. Por isso, cada tipo de estrutura de dados possuem vantagens e desvantagens e cada uma delas tem sua rea de atuao (massa de dados) tima. O aluno at aqui, somente teve contato com estruturas de dados estticas (vetores e matrizes), e deve estar familiarizado com suas facilidades e dificuldades de uso. Agora novas estruturas de dados sero apresentadas, sendo que, todas elas sero estruturas de dados dinmicas, ou seja, crescem e diminuem de acordo com a necessidade, veremos que, para isso, sero necessrias vrias rotinas que controlam esta dinamicidade das estruturas.

2. Tipos de Dados
A matemtica classifica suas variveis de acordo com as caractersticas, distinguindo constantes, equaes, conjuntos e funes. Em computao precisamos identificar os tipos de dados que o computador, a linguagem de programao ou mesmo um algoritmo sero capazes de entender. De uma forma geral diferenciamos os tipos de dados pelo conjunto de valores que podem assumir e pelo conjunto de operaes que podemos efetuar com eles. Por exemplo, poderamos definir que fruta um tipo de dado que pode assumir apenas os valores ma, pra, banana e abacaxi, sobre os quais podemos efetuar as operaes de comparar, comprar, comer e servir.

2.1 Primitivos, Estticos e Dinmicos


Podemos separar os tipos de dados em trs grupos: primitivos, estticos e dinmicos. Os tipos primitivos so aqueles a partir dos quais podemos definir os demais tipos, no importando como so implementados e manipulados. So considerados tipos primitivos nmeros inteiros, nmeros reais, caracteres, lgicos e ponteiros. Esses tipos de dados so os mais freqentes nas linguagens de programao. Cada um desses tipos primitivos tem um conjunto de valores e operaes restrito: Inteiro - Representa uma quantidade contvel de objetos. Operaes: Soma, Subtrao, Multiplicao, Diviso, Resto. Exemplos: -45; 2; 1037 Real - Representa um valor que pode ser fracionado. Operaes: Soma, Subtrao, Multiplicao. Exemplos: -4,78; 1,25; 2,333... Lgico - Representa dois estados. Operaes: E, NO, OU. Exemplos: [Verdadeiro, Falso];[1,0] Literal - Representa uma seqncia de dgitos, letras e sinais. Operaes: Igualdade, Diferena, Concatenao. Exemplos: A, X, 1, + Ponteiro - Representa o endereo de um dado na memria. Operaes: Igualdade, Diferena, Soma, Subtrao, Multiplicao, Diviso. A definio do conceito de tipos estticos e dinmicos pode ser feita de forma fsica ou lgica. Utilizaremos a forma lgica que corresponde ao modo como definimos todas as estruturas de dados. Definimos tipos estticos de dados como aqueles que tm a estrutura completamente definida antes de comearmos a efetuar operaes. O exemplo que sobressai o de que, definido um tipo esttico de dado, ele no poder conter mais elementos do que o previsto inicialmente. No s a limitao de elementos torna um tipo de dados esttico, como tambm seus sucessores e antecessores no se modificam (observe que o contedo pode ser modificado, mas no as suas posies na memria). Dessa forma a estrutura permanece esttica. Um exemplo de estrutura esttica o vetor, que um agregado homogneo de dados. Em contrapartida, os tipos dinmicos de dados so aqueles que sofrem alterao estrutural quando esto sendo manipulados, medida que ocorrem inseres e retiradas de elementos. Esse tipo de dado no tem tamanho predefinido, s ficando limitado memria do computador em que se est trabalhando. Do ponto de vista lgico, um tipo dinmico no tem limitaes, porm, como os algoritmos de manipulao dessas estruturas so implementados em computadores, neste texto trataremos as suas limitaes fsicas.

3. Variveis
3.1 Variveis Compostas Homogneas
Correspondem a posies de memria, identificadas por um mesmo nome, individualizadas por ndices e cujo contedo de mesmo tipo. O conjunto de 10 notas dos alunos de uma disciplina pode constituir uma varivel composta. A este conjunto associa-se o identificador Nota que passar a identificar no uma nica posio de memria, mas 10. A referncia ao contedo do n-simo elemento do conjunto ser indicada pela notao NOTA[n], onde n um nmero inteiro ou uma varivel numrica contendo um valor inteiro.

3.1.1 Variveis Compostas unidimensionais


Conjuntos de dados referenciados por um mesmo nome e que necessitam de somente um ndice para que seus elementos sejam endereados so ditos compostos unidimensionais. Ex. Vetores.

3.1.2 Variveis Compostas multidimensionais


Conjuntos de dados referenciados por um mesmo nome e que necessitam de mais de um ndice para ter seus elementos individualizados e dito multidimensional. Ex. Matrizes.

3.2 Variveis Compostas Heterogneas 3.2.1 Registros


So conjuntos de dados logicamente relacionados, mas de tipos diferentes (numrico, literal, lgico). Ex. Register, Struct, Class, etc.

3.2.2 Conjunto de Registros


Pode se ter conjuntos de registros referenciveis por um mesmo nome e individualizados por ndices. Ex. Vetor ou Matriz de Registro.

4. Listas Lineares
4.1 Motivao
Freqentemente nos deparamos, na soluo de determinados problemas, com conjuntos de dados que se relacionam entre si de alguma forma, refletindo algumas propriedades que estes dados apresentam no problema real. Naturalmente, desejamos que este relacionamento seja preservado, com o objetivo de se poder fazer uso do mesmo, quando estes forem representados no computador. Considere, por exemplo, o caso de um problema que envolva a manipulao de dados de precipitaes pluviomtricas dirias de um perodo de um ms. Se o problema consistir em obter-se, digamos a precipitao pluviomtrica mdia do perodo, no h nenhuma necessidade de se conhecer o relacionamento existente entre os dados dirios. Se, entretanto, o problema consistir em determinar uma funo que expresse o fenmeno (Ex. precipitao X tempo) no perodo, ento necessrio conhecer-se a relao de ordem cronolgica dos dados. Naturalmente, a relao de ordem no o nico tipo de relao que podemos encontrar entre dados.

4.2 Conceituao
A estrutura que permite representar um conjunto de dados de forma a preservar a relao de ordem linear(ou total) entre eles a lista linear. Uma lista linear composta de ns, os quais podem conter, cada um deles, um dado primitivo ou um dado composto. Define-se uma lista linear como sendo o conjunto de n>=0 ns x1, x2, ... , xn, organizados estruturalmente de forma a refletir as posies relativas dos mesmos: se n>0, ento x1 o primeiro; para 1< k < n, o n xk precedido pelo xk-1 e seguido do xk+1; e xn o ltimo n. Quando n=0, dizemos que a lista est vazia. Uma outra definio segundo Villas et al : Uma lista linear uma estrutura dinmica caracterizada por uma seqncia ordenada de elementos, no sentido da sua posio relativa. Existem vrios exemplos de listas lineares, tais como: Fila de Clientes em um banco: existe o primeiro da fila, o ltimo da fila e os clientes fazem com exista uma ordem de atendimento; Fichrio: existe um nmero finito de fichas que est agrupado segundo uma ordem preestabelecida, de tal forma que conseguimos identificar a terceira ficha. a dcima ficha, etc.

4.3 Operaes
Uma vez decidido que um conjunto de dados ser representado sob a forma de uma lista linear, devemos tambm decidir que operaes podem (ou devem) ser efetuado sobre esta lista. Por exemplo, uma lista de alunos inscritos em um curso podemos verificar a presena de alunos (localizar), novos alunos so matriculados (inserir), e alguns alunos eventualmente desistem (remover) e outros alunos precisar modificar os dados da matricula (alterar). Normalmente, estas operaes incluem: a) b) c) d) e) f) localizar o k-simo n da lista, para obter o dado nele contido; alterar o k-simo n da lista, para alterar o dado nele contido; inserir um novo n aps (ou antes) o k-simo n da lista;(Inicio, Meio, Fim, Ordenado) remover o k-simo n da lista; (Inicio, Meio, Fim) determinar o nmero de ns de uma lista (Contar) concatenar duas listas;

Naturalmente, a escolha das operaes a serem efetuadas sobre as listas depender fortemente da soluo proposta para o problema, e vice-versa.

4.4 Classificao
Resumidamente, as seguintes variaes de listas lineares podem ser consideradas: lista linear seqencial (ou contgua) lista linear seqencial (ou contgua) com disciplina de acesso LIFO (pilha) lista linear seqencial (ou contgua) com disciplina de acesso FIFO (fila) lista linear simplesmente encadeada (ou ligada) com ou sem descritor lista linear simplesmente encadeada (ou ligada) circular lista linear duplamente encadeada (ou ligada) com ou sem descritor lista linear encadeada (ou ligada) com disciplina de acesso LIFO (pilha) lista linear encadeada (ou ligada) com disciplina de acesso FIFO (fila)

4.5 Representaes
Existem vrias formas possveis de se representar internamente uma lista linear. A escolha de uma destas formas depender da freqncia com que determinadas operaes sero executadas sobre a lista, uma vez que algumas representaes so favorveis a algumas operaes, enquanto que outras no o so, no sentido de exigir um maior esforo computacional para a sua execuo. As duas formas mais freqentemente usadas para representar listas lineares so por contigidade dos ns e por encadeamento dos ns.

4.5.1 Contigidade
A representao por contigidade explora a seqencialidade da memria do computador, de tal forma que os ns de uma lista sejam armazenados em endereos contguos, ou igualmente distanciados um do outro. Neste caso, a relao de ordem entre os ns da lista representado pelo fato de que se o endereo do n xi conhecido, ento o endereo do n xi+1 pode ser determinado. Esquematicamente, a representao de uma lista linear por contigidade tem a forma mostrada abaixo. x1 x2 x3 ... ... ... ... xn-1 xn

Figura 1 Esquema lista linear contgua

A implementao pode ser feita utilizando vetor e registro, onde o vetor associa o elemento xi com o ndice i (mapeamento seqencial).

4.5.1.1 Caractersticas
elementos na lista esto ordenados; armazenados fisicamente em posies consecutivas; insero em um elemento na posio xi causa o deslocamento a direita do elemento xi ao ltimo; remoo do elemento xi requer o deslocamento esquerda do xi+1 ao ltimo;

4.5.1.2 Vantagens
Acesso direto indexado a qualquer elemento da lista; Tempo constante para acessar o elemento i depender somente do ndice. Facilidade de implementao das operaes.

4.5.1.3 Desvantagens
Movimentao de elementos quando ocorrer uma insero ou remoo de elementos; Tamanho mximo pr-definido.

4.5.1.4 Quando Usar


Listas pequenas; Insero e Remoo no fim da lista; Tamanho mximo bem definido.

4.5.2 Encadeamento
Na contigidade vimos que algumas operaes (insero e remoo de ns) sobre listas lineares exigem um grande esforo computacional, o que pode ser um fator determinante do baixo desempenho do programa, caso estas operaes sejam freqentemente executadas. Alm disso, necessrio fazer-se, a priori, uma estimativa do comprimento mximo que a lista pode tomar, para que o vetor que a contiver seja declarado com este tamanho. Caso haja uma tentativa de ultrapassar o comprimento mximo permitido, o processamento ter de ser interrompido, pois o vetor no pode, ter o seu tamanho alterado dinamicamente para permitir a representao de uma lista de comprimento maior do que o inicialmente previsto. Uma forma de permitir o crescimento dinmico do comprimento mximo de uma lista, bem como diminuir o esforo computacional das operaes de insero e remoo de ns, representar a lista por encadeamento, onde os ns so ligados entre si para indicar a relao de ordem existente entre eles. Assim, cada n, alm de conter o dado propriamente dito, dever conter tambm a indicao do n seguinte, caso haja algum. Dizemos que a contigidade dos mesmos lgica. Esquematicamente, uma lista encadeada representada por: x1 x2 ...
Figura 2 Esquema Lista Encadeada

xn-1

xn

O mecanismo lingstico que permite a implementao desta estrutura a referncia, que prov a alocao dinmica de ns. Supondo que cada n deva conter um dado do tipo TipoDado, definido pelo usurio, a sua definio a seguinte:
Tipo No : Registro dado : TipoDado proximo : No Fim_registro

Isto , cada n ser um agregado do tipo registro, com dois componentes: um para representar o dado e outro que indica qual o prximo n da lista, como mostra a figura abaixo. dado proximo

Figura 3 - Estrutura N

4.5.2.1 Vantagens
No requer mais a movimentao de ns na insero e remoo (como na lista seqencial); Apenas os ponteiros so alterados (lembre que cada registro pode conter elementos mais complexos);

10

No necessrio prever o tamanho da lista; Otimizao da memria.

4.5.2.2 Desvantagens
O acesso no indexado, para acessar xi temos que percorrer x1... xn-1 pois o endereo xi est apenas em de xn-1; Dificuldade de implementao;

4.5.2.3 Quando Usar


Listas grandes e muito utilizadas; Operaes em qualquer posio da lista; Tamanho mximo no definido; Otimizar a memria.

4.5.3 Tipo Apontador (Ponteiro)


Um das caractersticas mais marcantes da programao permitir a criao e destruio de variveis durante a execuo de um programa. O uso dessas variveis possibilita a implementao das estruturas de dados dinmicas. Essas variveis criadas e destrudas durante a execuo do programa so chamadas variveis dinmicas. Uma varivel dinmica no declarada na parte de declarao de variveis porque esta ainda no existe antes do seu tempo de execuo, ela no possui sequer um nome, ficando a cargo dos ponteiros desempenhar esta funo de nome. Uma varivel dinmica sempre referenciada indiretamente por um apontador, ou seja, para cada varivel dinmica criada deve existir um apontador, que literalmente aponta para ela, permitindo a sua manipulao.

4.5.3.1 Caractersticas Gerais


Os apontadores so declarados como as demais variveis, seguindo a sintaxe da linguagem de programao utilizada. Eles so variveis que armazenam o endereo de memrias de outras variveis, funcionando assim, como meio de referenciar uma varivel dinmica, permitindo o acesso a essa varivel. Outra caracterstica dos apontadores que na sua declarao deve ser indicada qual o tipo de varivel este ir armazenar o endereo. A principal funo dos ponteiros permitir a criao e a manipulao das variveis dinmicas, as quais iro compor as estruturas de dados dinmicas.

4.5.4 Uso da Memria


Informalmente, podemos dizer que existem trs maneiras de reservar espao de memria para o armazenamento de informaes: A primeira usar variveis globais (e estatsticas). O espao reservado para uma varivel global existe apenas enquanto o programa estiver sendo executado. A segunda maneira usar variveis locais. Nesse caso, o espao existe apenas enquanto a subrotina que declarou a varivel est sendo executada, sendo liberado para outros usos quando a execuo da sub-rotina termina. A terceira maneira de reservar memria requisitar ao sistema, em tempo de execuo, um espao de um determinado tamanho. Esse espao alocado dinamicamente permanece reservado at que seja explicitamente liberado pelo programa. A figura abaixo ilustra de maneira fictcia a distribuio do uso da memria pelo sistema operacional. Ao carregar um programa o sistema operacional aloca espao para o cdigo do programa, variveis globais e reserva um espao para as variveis dinmicas e as chamadas de sub-rotinas. Este espao para as variveis dinmicas e sub-rotinas tambm e chamado de heap. Cada vez que uma sub-rotina chamada o sistema reserva um espao para as variveis locais da sub-rotina. Esse espao pertence pilha de execuo e, quando a sub-rotina termina, desempilhada. Se a

11

pilha tentar crescer alm do espao disponvel existente, dizemos que ela estourou (stack overflow), e o programa abortado com erro. Da mesma forma, se o espao de memria livre for menor do que o espao requisitado dinamicamente, a alocao no realizada, e o programa pode prever um tratamento de erro adequado (por exemplo, podemos imprimir a mensagem Memria Insuficiente e interromper a execuo do programa).
Cdigo do Programa Variveis Globais e Estticas Memria Alocada Dinamicamente

Memria Livre

Pilha
Figura 4 - Alocao esquemtica de memria

12

5. Listas Lineares Seqenciais


5.1 Representao Genrica
1 2 3 4 5 6 7 8 ... n-1 n

Figura 5 - Representao Genrica Lista Linear

5.2 Caractersticas:
so implementadas atravs de variveis estticas; o acesso aos seus componentes feito de maneira direta (atravs de um ndice, por exemplo); as estruturas de representao que melhor permitem a implementao de listas lineares seqenciais (ou contguas) so os arrays e arquivos.

5.3 Vantagens
Alm de todas as vantagens inerentes a manipulao de variveis estticas, tambm tm como caracterstica marcante o fato de poderem ser implementadas em praticamente todas as linguagens de programao mais utilizadas (Java, C+, C, Pascal, COBOL, Fortran, Clipper etc).

5.4 Desvantagens
Tambm traz todas as desvantagens inerentes a manipulao de variveis estticas, como por exemplo, a necessidade de se prefixar seu tamanho inicial, a impossibilidade de se redimensionar este tamanho pr-fixado em tempo de execuo, a dificuldade em se realizar sobre ela certas operaes (insero e remoo, por exemplo) etc. Ex.: para a lista lineares seqencial abaixo, que contm uma lista de nomes arranjadas em ordem alfabtica, a incluso de um novo nome (Benedito, por exemplo), acarretaria a necessidade de se rearranjar todos os nomes a partir de Carlos, para poder abrir espao para a incluso do novo nome.
1 2 3 4 5 6 7 8 9 10 11 12 13 .... n-1 n Aaro Carlos Clia Dalva Eldio Fbio Francisco Gustavo Hlio Iria Joaquim Jos Ktia Zaqueu Zulmira

Figura 6 - Lista linear seqencial de nomes

Aps a incluso do novo nome, novas incluses seriam impossveis, visto que no mais haveria espao disponvel para tanto.

13

5.5 Implementaes 5.5.1 Lista K


Algoritmo Programa_Lista_K Constante TAMANHO = 100 Tipo TipoDado TipoLista

: Inteiro : VETOR [1:TAMANHO] de TipoDado

Variveis Lista N, opcao , K, I Val sin

: : : :

TipoLista Inteiro TipoDado Lgico

Inicio N 0 opcao -1 // Menu para chamada das operaes de uma lista Enquanto opo <> 9 faa Escreva(" 1 Inserir 2 Alterar 3 Remover 4 Acessar 5 Listar 9 Sair") Leia(opcao) Se opcao = 1 ento Escreva("Qual a posio a ser inserida? ") Leia K Escreva(Qual o valor a inserir? ) Leia Val sin .F. inserir(lista,K,N,sin,Val) Se sin = .V. ento Escreva(O valor inserido com sucesso) Fim_se Seno Se opcao = 2 ento Escreva(Qual a posio a ser alterada? ) Leia K Escreva(Qual o novo valor? ) Leia Val sin .F. alterar(lista,K,N,sin,Val) Se sin = .V. ento Escreva(O valor alterado com sucesso) Fim_se Seno Se opcao = 3 Ento Escreva(Qual a posio a ser removida? ) Leia K sin .F. remover(lista,K,N,sin) Se sin = .V. ento Escreva(O valor removido com sucesso) Fim_se Seno Se opcao = 4 Ento Escreva(Qual a posio k a ser consultada?) Leia K sin .F.

14

acessar(lista,K,N,sin,val) Se sin = .V. ento Escreva(Elemento Consultado (+K+) = + val) Fim_se Seno Se opcao = 5 Ento Escreva (Listagem) Para I de 1 at N passo + 1 Faa Escreva (i + - + lista[i]) Fim_para Escreva (Total Fila : + N) Fim_se Fim_se Fim_se Fim_se Fim_se Fim_enquanto Fim. //Sub-rotina inserir tem os argumentos _valor, _k passados por valor. Os argumentos _lista, _fim e _sinal so passados por referncia pois _sinal indicar se inseriu um novo no, _fim ser incrementado em 1 por causa do novo elemento e _lista ter um novo elemento inserido. Sub-rotina inserir(ref _lista : TipoLista; _k : Inteiro; ref _fim : Inteiro; ref _sinal : Lgico; _valor : TipoDado) Variveis i : Inteiro Inicio Se _fim < TAMANHO Ento Se _k > 0 e _k <= _fim+1 Ento Para i de _fim at _k passo - 1 faa _lista[i+1] _lista[i] Fim_para _fim _fim + 1 _lista[_k] _valor _sinal .V. Seno _sinal .F. Fim_se Seno _sinal .F. Escreva(Lista Cheia) Fim_se Fim //Sub-rotina alterar tem os argumentos _valor, _k, _fim passados por valor. Os argumentos _lista e _sinal so passados por referncia, pois _sinal indicar se alterou o no e _lista ter um elemento alterado. Sub-rotina alterar(ref _lista : TipoLista; _k, _fim : Inteiro; ref _sinal : Lgico; _valor : TipoDado) Inicio Se _k > 0 e _k <= _fim Ento _lista[_k] _valor _sinal .V. Seno _sinal .F. Fim_se Fim //Sub-rotina remover tem os argumentos _k passados por valor. Os argumentos _lista, _fim e _sinal so passados por referncia pois _sinal indicar se

15

removeu um no, _fim ser decrementado em 1 e _lista ter um elemento removido. Sub-rotina remover(ref _lista : TipoLista; _k : Inteiro; ref _fim : Inteiro; ref _sinal : Lgico) Variveis i : Inteiro Inicio Se _k > 0 e _k <= _fim Ento Para i de _k at _fim passo +1 faa _lista[i] _lista[i+1] Fim_para _fim _fim - 1 _sinal .V. Seno _sinal .F. Fim_se Fim //Sub-rotina acessar tem os argumentos lista, _k, _fim passados por valor. Os argumentos _sinal e _valor so passados por referncia, pois _sinal indicar se encontrou o no e valor retorna o valor do no. Sub-rotina acessar(_lista : TipoLista; _k, _fim : Inteiro; ref _sinal : Lgico; ref _valor : TipoDado) Inicio Se _k > 0 e _k <= _fim Ento _valor _lista[_k] _sinal .V. Seno _sinal .F. Fim_se Fim

16

5.5.2 Lista Operaes


Algoritmo Programa_Lista_K Constante TAMANHO = 100 Tipo TipoDado TipoLista

: Inteiro : VETOR [1:TAMANHO] de TipoDado

Variveis Lista N, opcao , K, I val sin

: : : :

TipoLista Inteiro TipoDado Lgico

Inicio N 0 opcao -1 // Menu para chamada das operaes de uma lista Enquanto opo <> 10 faa Escreva(1 Inserir Inicio 2 Inserir K 3- Inserir Fim 4 Remover Inicio 5 Remover K 6 - Remover Fim 7 - Alterar K 8 Acessar K 9 Listar 10 Sair) Leia(opcao) Se opcao = 1 ento Escreva(Qual o valor a inserir no inicio ? ) Leia val sin .F. inserirInicio(lista, N,sin,val) //K = 1 Se sin = .V. ento Escreva(O valor inserido no inicio com sucesso) Fim_se Seno Se opcao = 2 ento Escreva(Qual a posio a ser inserida? ) Leia K Escreva(Qual o valor a inserir na posio K? ) Leia val sin .F. inserirK(lista,K,N,sin,val) //K lido Se sin = .V. ento Escreva(O valor inserido na posio K com sucesso) Fim_se Seno Se opcao = 3 ento Escreva(Qual o valor a inserir no fim? ) Leia val sin .F. inserirFim(lista, N,sin,val) //K = N Se sin = .V. ento Escreva(O valor inserido no fim com sucesso) Fim_se Seno Se opcao = 4 ento sin .F. removerInicio(lista, N,sin) Se sin = .V. ento Escreva(O valor removido do incio com sucesso) Fim_se Seno

17

Se opcao = 5 ento Escreva(Qual a posio a ser removida? ) Leia K sin .F. removerK(lista,K,N,sin) Se sin = .V. ento Escreva(O valor removido da posio K com sucesso) Fim_se Seno Se opcao = 6 Ento sin .F. removerFim(lista, N,sin) Se sin = .V. ento Escreva(O valor removido do fim com sucesso) Fim_se Seno Se opcao = 7 Ento Escreva(Qual a posio a ser alterada? ) Leia K Escreva(Qual o novo valor? ) Leia val sin .F. alterar(lista,K,N,sin,val) Se sin = .V. ento Escreva(O valor alterado com sucesso) Fim_se Seno Se opcao = 8 Ento Escreva(Qual a posio k a ser consultada? ) Leia K sin .F. acessar(lista,K,N,sin,val) Se sin = .V. ento Escreva(O valor de +K+ e + val) Fim_se Seno Se opcao = 9 Ento Escreva (Listagem) Para I de 1 at N passo + 1 Faa Escreva (i + - + lista[i]) Fim_para Escreva (Total Lista : + N) Fim_se //9 Fim_se //8 Fim_se //7 Fim_se //6 Fim_se //5 Fim_se //4 Fim_se // 3 Fim_se //2 Fim_se //1 Fim_enquanto Fim. //Sub-rotina inserirInicio tem os argumento _valor passado por valor. Os argumentos _lista, _fim e _sinal so passados por referncia, pois _sinal indicar se inseriu um novo no, _fim ser incrementado em 1 por causa do novo elemento e _lista ter um novo elemento inserido. Sub-rotina inserirInicio(ref _lista : TipoLista; ref _fim : Inteiro; ref _sinal : Lgico; _valor : TipoDado) Variveis

18

i : Inteiro Inicio Se _fim < TAMANHO Ento Para i de _fim at 1 passo - 1 faa _lista[i+1] _lista[i] Fim_para _fim _fim + 1 _lista[1] _valor _sinal .V. Seno _sinal .F. Escreva(Lista Cheia); Fim_se Fim //Sub-rotina inserirK tem os argumentos _valor, _k passados por valor. Os argumentos _lista, _fim e _sinal so passados por referncia, pois _sinal indicar se inseriu um novo no, _fim ser incrementado em 1 por causa do novo elemento e lista ter um novo elemento inserido. Sub-rotina inserirK(ref _lista :TipoLista; _k :Inteiro; ref _fim:Inteiro; ref _sinal:Lgico; _valor:TipoDado) Variveis i : Inteiro Inicio Se _fim < TAMANHO Ento Se _k > 0 e _k <= _fim+1 Ento Para i de _fim at _k passo - 1 faa _lista[i+1] _lista[i] Fim_para _fim _fim + 1 _lista[k] _valor _sinal .V. Seno _sinal .F. Fim_se Seno _sinal .F. Escreva(Lista Cheia); Fim_se Fim //Sub-rotina inserirFim tem os argumento _valor passado por valor. Os argumentos _lista, _fim e _sinal so passados por referncia pois, _sinal indicar se inseriu um novo no, _fim ser incrementado em 1 por causa do novo elemento e _lista ter um novo elemento inserido. Sub-rotina inserirFim(ref _lista : TipoLista; ref _fim : Inteiro; ref _sinal : Lgico; _valor : TipoDado) Variveis i : Inteiro Inicio Se _fim < TAMANHO Ento _fim _fim + 1 _lista[_k] _valor _sinal .V. Seno _sinal .F. Escreva(Lista Cheia); Fim_se Fim

19

//Sub-rotina removerInicio os argumentos _lista, _fim e _sinal so passados por referncia pois _sinal indicar se removeu um no, _fim ser decrementado em 1 e _lista ter um elemento removido. Sub-rotina removerInicio(ref _lista : TipoLista; ref _fim : Inteiro; ref _sinal : Lgico) Variveis i : Inteiro Inicio Se _fim <> 0 Ento Para i de 1 at _fim passo +1 faa _lista[i] _lista[i+1] Fim_para _fim _fim - 1 _sinal .V. Seno _sinal .F. Fim_se Fim //Sub-rotina remover tem os argumentos _k passados por valor. Os argumentos _lista, _fim e _sinal so passados por referncia pois _sinal indicar se removeu um no, _fim ser decrementado em 1 e _lista ter um elemento removido. Sub-rotina removerK(ref _lista : TipoLista; _k : Inteiro; ref _fim : Inteiro; ref _sinal : Lgico) Variveis i : Inteiro Inicio Se _fim <> 0 Ento Se _k > 0 e _k <= _fim Ento Para i de _k at _fim passo +1 faa _lista[i] _lista[i+1] Fim_para _fim _fim - 1 _sinal .V. Seno _sinal .F. Fim_se Seno _sinal .F. Fim_se Fim //Sub-rotina removerFim os argumentos _lista, _fim e _sinal so passados por referncia pois _sinal indicar se removeu um no, _fim ser decrementado em 1 e _lista ter um elemento removido. Sub-rotina removerFim(ref _lista : TipoLista; ref _fim : Inteiro; ref _sinal : Lgico) Variveis i : Inteiro Inicio Se _fim <> 0 Ento _lista[_fim] 0; _fim _fim - 1 _sinal .V. Seno _sinal .F. Fim_se Fim

20

//Sub-rotina alterar tem os argumentos _valor, _k, _fim passados por valor. Os argumentos _lista e _sinal so passados por referncia pois, _sinal indicar se alterou o no e _lista ter um elemento alterado. Sub-rotina alterar(ref _lista : TipoLista; _k, _fim : Inteiro; ref _sinal : Lgico; _valor : TipoDado) Inicio Se _k > 0 e _k <= _fim Ento _lista[_k] _valor _sinal .V. Seno _sinal .F. Fim_se Fim //Sub-rotina acessar tem os argumentos _lista, _k, _fim passados por valor. Os argumentos _sinal e _valor so passados por referncia pois, _sinal indicar se encontrou o no e valor retorna o valor do no. Sub-rotina acessar(_lista : TipoLista; _k, _fim : Inteiro; ref _sinal : Lgico; ref _valor : TipoDado) Inicio Se _k > 0 e _k <= _fim Ento _valor _lista[_k] _sinal .V. Seno _sinal .F. Fim_se Fim

21

6. Listas Lineares com Disciplina de Acesso


Para determinadas aplicaes imposto um critrio que restringe a insero e remoo de elementos que compem um conjunto de dados. O critrio escolhido impe uma ordem ao conjunto, ordem esta que em geral no depende da ordem natural dos valores dos dados. Os dois critrios mais usuais so: Critrio LIFO (Last In First Out): dentre os elementos que ainda permanecem no conjunto, o primeiro elemento a ser retirado o ltimo que tiver sido inserido; Critrio FIFO (First In First Out): dentre os elementos que ainda permanecem no conjunto, o primeiro elemento a ser retirado o primeiro que tiver sido inserido.

Estruturas lineares com essas disciplinas de acesso so denominadas pilhas (critrio LIFO) e filas (critrio FIFO). Estas estruturas disciplinadas no ocorrem somente em computao. O critrio FIFO o que rege o funcionamento de uma fila de pessoas em um guich: as pessoas so atendidas na ordem em que chegaram. J o critrio LIFO corresponde a uma pilha de livros, por exemplo: um novo livro colocado no topo da pilha e s podemos retirar o volume do topo; de outro modo pilha desabaria. Para ter acesso a um livro que est abaixo do topo, primeiro, retirar os que esto por cima dele.

6.1 Pilhas 6.1.1 Definio


Uma pilha uma lista linear de informao que acessada na seguinte ordem, o ltimo que entra, primeiro que sai isto pr-define a posio de insero e remoo. Uma pilha no permite acesso a um elemento que no seja o primeiro. Esta disciplina de acesso conhecida por LIFO - "Last In First Out", ou em sua forma aportuguesada, UEPS - "ltimo a Entrar Primeiro a Sair". Pilha uma lista na quais as operaes de insero e remoo de elementos executadas em somente uma das extremidades, denominada topo da lista. Desta forma, o ltimo elemento inserido o primeiro a ser removido. A representao dos vrios momentos de uma pilha mostrada a seguir:

Figura 7 - Representao dos vrios momentos de uma pilha

A figura comprova as caractersticas principais das pilhas, que a insero e remoo efetuadas somente sobre o ltimo elemento (topo da lista). interessante notar que no possvel distinguir a pilha nos instantes 1 e 5 ou 2 e 4, uma vez que nestes instantes, a pilha contm itens idnticos, empilhados na mesma ordem e com topos idnticos. Isto acontece uma vez que a estrutura pilha no mantm nenhum registro dos elementos que lhe so inseridos ou removidos. No caso deste registro se fazer necessrio, deve ser mantido a parte.

22

Na realidade, esta viso lateral dos arranjos de uma pilha no verdadeira, sendo, no entanto a mais didtica. Para o entendimento real de como a pilha tratada pelo computador, ela deve ser olhada de cima para baixo. Deste ponto de vista, no seria possvel, por exemplo, diferenciar a pilha nos instantes 2 e 7, uma vez que esta viso somente nos permite visualizar o topo da pilha, isto , a letra G.

6.1.2 Aplicao
Um bom exemplo da aplicao das pilhas a gerencia das chamadas as sub-rotinas utilizadas pela maioria dos compiladores das linguagens de programao. No cotidiano existem inmeros exemplos de aplicaes nas quais utilizada a disciplina de acesso. A disciplina LIFO, como por exemplo, em uma pilha de pratos ou de livros, um pacote de bolacha gua e sal, a mudana acomodada em um caminho de mudanas, os anis em um dedo da mo, ou ainda um elevador de pessoas gordas, onde somente depois que o ltimo que entrou sair, ser possvel aos outros sarem tambm.

6.1.3 Operaes Bsicas


Por razes histricas, as duas operaes primrias de pilha so: insero de elementos push ou empilhar retirada de elementos pop ou desempilhar

Dada a pilha p e um item i qualquer, define-se a operao push(p,i) como a adio do item i no topo da pilha p. De forma similar, a operao pop(p) definida como a operao que remove um elemento do topo da pilha p. Por exemplo, x pop(p), vai remover o elemento constante no topo da pilha p e armazen-lo na varivel x. Na figura anterior, os 7 momentos seriam representados da seguinte maneira, utilizando-se das operaes push e pop: 2 - push(p,g) 5 - pop(p) 3 - push(p,h) 6 - pop(p) 4 - pop(p) 7 - push(p,g)

Teoricamente, no existe um limite superior para o nmero de elementos na pilha, ou seja, seria possvel a colocao infinita de novos elementos em uma pilha. Por outro lado, se uma pilha p possui somente um elemento, e objeto de uma operao de remoo {pop(p)}, a pilha resultante uma pilha vazia, que no possui mais nenhum elemento para ser retirado. Uma maneira de se garantir que uma operao pop(p) no seja efetuada em uma pilha vazia definio de uma 3 operao para a manipulao de pilhas, denominada empty(p) ou pilha vazia, que retorna um valor booleano VERDADE caso a pilha esteja vazia, e FALSO caso contrrio. Uma 4 operao que pode ser definida para a manipulao de pilhas a verificao de qual elemento se encontra no topo da pilha em um determinado momento. Esta operao poderia ser denominada TOPO_PILHA, e seria equivalente a: i pop(p); push(p,i); A operao TOPO_PILHA, assim como POP no pode ser aplicada em uma pilha vazia. Caso se aplique uma destas 2 operaes em uma pilha vazia, incorre-se em um erro conhecido como underflow (tentativa de se retirar um elemento de uma pilha vazia).

23

6.1.4 Implementao de Pilha com Lista Seqencial


Algoritmo Programa_Pilha Constante TAMANHO = 100 Tipo TipoDado TipoLista

: Inteiro : VETOR[1:TAMANHO] de TipoDado

Variveis pilhaLista N, opcao , K, I val sin

: : : :

TipoLista Inteiro TipoDado Lgico

Inicio N 0 opcao -1 // Menu para chamada das operaes de uma Pilha Enquanto opo <> 9 faa Escreva( 1 Empilhar 2 Acessar Topo 3 Alterar Topo 4 Desempilhar 5 Listar Pilha 9 Sair) Leia(opcao) Se opcao = 1 ento Escreva(Qual o valor a Empilhar? ) Leia val sin .F. empilhar(lista,N+1,N,sin,val) Se sin = .V. ento Escreva(O valor empilhado com sucesso) Fim_se Seno Se opcao = 2 ento sin .F. acessarTopo(lista,N,N,sin,val) Se sin = .V. ento Escreva(O valor do topo e + val) Fim_se Seno Se opcao = 3 Ento Escreva(Qual o novo valor do topo? ) Leia val sin .F. alterarTopo(lista,N,N,sin,val) Se sin = .V. ento Escreva(O valor do topo alterado com sucesso) Fim_se Seno Se opcao = 4 Ento sin .F. desempilhar(lista,N,N,sin) Se sin = .V. ento Escreva(O topo removido com sucesso) Fim_se Seno Se opcao = 5 Ento Escreva (Listagem) Para I de 1 at N passo + 1 Faa Escreva (i + - + lista[i]) Fim_para

24

Escreva (Total Fim_se Fim_se Fim_se Fim_se Fim_se Fim_enquanto Fim.

Pilha : + N)

//Sub-rotina empilhar ou push tem os argumentos _valor, _k passados por valor. Os argumentos _lista, _fim e _sinal so passados por referncia pois, _sinal indicar se realizou o empilhamento, _fim ser incrementado em 1 por causa do novo elemento e _lista ter um novo elemento empilhado. Sub-rotina empilhar(ref _lista : TipoLista; _k : Inteiro; ref _fim : Inteiro; ref _sinal : Lgico; _valor : TipoDado) Variveis i : Inteiro Inicio Se _fim < TAMANHO Ento Se _k > 0 e _k <=_fim+1 Ento //Nunca usa o lao pois, inclui somente no fim Para i de _fim at _k passo - 1 faa _lista[i+1] _lista[i] Fim_para _fim _fim + 1 _lista[_k] _valor _sinal .V. Seno _sinal .F. Fim_se Seno _sinal .F. Escreva(Pilha Cheia) Fim_se Fim //Sub-rotina acessarTopo tem os argumentos _lista, _k, _fim passados por valor. Os argumentos _sinal e _valor so passados por referncia pois, _sinal indicar se encontrou o topo e _valor retorna o valor do topo. Sub-rotina acessarTopo(_lista : TipoLista; _k, _fim : Inteiro; ref _sinal : Lgico; ref _valor : TipoDado) Inicio Se _k > 0 e _k <= _fim Ento _valor _lista[_k] _sinal .V. Seno _sinal .F. Fim_se Fim //Sub-rotina alterarTopo tem os argumentos _k, _fim e _valor passados por valor. Os argumentos _lista e _sinal so passados por referncia pois, _sinal indicar se alterou o topo e _lista ter um elemento alterado. Sub-rotina alterarTopo(ref _lista : TipoLista; _k, _fim : Inteiro; ref _sinal : Lgico; _valor : Inteiro) Inicio Se _k > 0 e _k <= _fim Ento _lista[_k] valor _sinal .V. Seno _sinal .F.

25

Fim_se Fim //Sub-rotina desempilhar ou pop tem os argumento _k passado por valor. Os argumentos _lista, _fim e _sinal so passados por referncia pois, _sinal indicar se desempilhou, _fim ser decrementado em 1 e _lista ter um elemento desempilhado. Sub-rotina desempilhar(ref _lista : TipoLista; _k : Inteiro; ref _fim : Inteiro; ref _sinal : Lgico) Variveis i : Inteiro Inicio Se _k > 0 e _k <= _fim Ento // Nunca usa o lao, pois exclui somente do fim Para i de _k at _fim passo +1 faa _lista[i] _lista[i+1] Fim_para _fim _fim - 1 _sinal .V. Seno _sinal .F. Fim_se Fim

26

6.2 Filas 6.2.1 Definio


Uma fila uma lista linear de informao que acessada na seguinte ordem, o primeiro que entra, primeiro que sai. Uma fila no permite acesso a um elemento que no seja o primeiro. A disciplina de acesso que rege a insero e remoo de elementos em uma fila denominada FIFO ("First In First Out"), ou em sua forma aportuguesada, PEPS ("Primeiro a Entrar Primeiro a Sair"). uma lista na qual os itens componentes devem ser deletados somente em uma extremidade denominada incio da fila, e os itens somente podem ser inseridos na outra extremidade, denominada final da fila. A figura abaixo apresenta uma fila em diversos momentos distintos:

Figura 8 - Diversos momentos de uma fila

6.2.2 Aplicao
Normalmente as filas so utilizadas na administrao de recursos compartilhados, impondo uma prioridade por ordem de chegada. Um bom exemplo so as filas de impresso, onde, cada documento espera sua vez para ser impresso.

6.2.3 Operaes Bsicas


Existem 3 operaes primitivas principais que podem ser aplicadas em uma fila: insero de elementos enqueue ou enfileirar, remoo de elementos dequeue ou desemfileirar fila vazia.

Define-se que: insere(f,x) - insere o elemento x no final da fila f. x remove(f) - remove o elemento inicial da fila f e o armazena na varivel x. vazio(f) - retorna VERDADE se a fila est vazia, ou FALSO, caso contrrio.

Desta forma, a fila apresentada na figura acima pode ser obtida segundo a seguinte seqncia de operaes: 1 insere(f,a insere(f,b) insere(f,c) 2 remove(f) insere(f,e) 3 insere(f,d)

Por definio, no existe limitao do nmero de elementos que uma fila pode conter, portanto, a operao de insero sempre pode ser realizada. No entanto, a prtica pode ser diferente, dependendo da estrutura de representao utilizada para representar a fila. No caso de se utilizar uma estrutura do tipo array, o limite superior de elementos que a fila pode conter igual ao nmero mximo de elementos do array. comum a utilizao de uma referncia para o incio e outro para o fim da fim, facilitando assim as operaes.

27

No caso de se tentar incluir um nmero maior de elementos que o suportado pela estrutura de representao, comete-se o erro do overflow. Por outro lado, a tentativa de se retirar um elemento de uma fila vazia constitui um erro de underflow.

6.2.4 Implementao de Fila com Lista Seqencial


Algoritmo Programa_Fila Constante TAMANHO = 100 Tipo TipoDado TipoLista

: Inteiro : VETOR[1:TAMANHO] de TipoDado

Variveis pilhaLista N, opcao , K, I val sin

: : : :

TipoLista Inteiro TipoDado Lgico

Inicio N 0 opcao -1 // Menu para chamada das operaes de uma Fila Enquanto opo <> 6 faa Escreva( 1 Enfileirar 2 Consultar Inicio 3 Alterar Inicio 4 Desenfileirar 5 Listar Fila 6 Sair) Leia(opcao) Se opcao = 1 ento Escreva(Qual o valor a Enfileirar? ) Leia val sin .F. enfileirar(lista,N+1,N,sin,val) Se sin = .V. ento Escreva(O valor enfileirado com sucesso) Fim_se Seno Se opcao = 2 ento sin .F. consultarInicio(lista,1,N,sin,val) Se sin = .V. ento Escreva(O valor do inicio da fila e + val) Fim_se Seno Se opcao = 3 Ento Escreva(Qual o novo valor do inicio da fila? ) Leia val sin .F. alterarInicio(lista,1,N,sin,val) Se sin = .V. ento Escreva(O valor do inicio da fila alterado com sucesso) Fim_se Seno Se opcao = 4 Ento sin .F. desenfileirar(lista,1,N,sin) Se sin = .V. ento Escreva(O valor foi desenfileirado com sucesso) Fim_se Seno

28

Se opcao = 5 Ento Escreva (Listagem) Para I de 1 at N passo + 1 Faa Escreva (i + - + lista[i]) Fim_para Escreva (Total Fila : + N) Fim_se Fim_se Fim_se Fim_se Fim_se Fim_enquanto Fim. //Sub-rotina enfileirar ou enqueue tem os argumentos _valor, _k passados por valor. Os argumentos _lista, _fim e _sinal so passados por referncia pois, _sinal indicar se realizou o empilhamento, _fim ser incrementado em 1 por causa do novo elemento e _lista ter um novo elemento empilhado. Sub-rotina enfileirar (ref _lista:TipoLista; _k:Inteiro; ref _fim:Inteiro; ref _sinal:Lgico; _valor:TipoDado) Variveis i : Inteiro Inicio Se _fim < TAMANHO Ento Se _k > 0 e _k <=_fim+1 Ento //Ser sempre usado pois s inclui no inicio da lista Para i de _fim at _k passo - 1 faa _lista[i+1] _lista[i] Fim_para _fim _fim + 1 _lista[_k] _valor _sinal .V. Seno _sinal .F. Fim_se Seno _sinal .F. Escreva(Fila Cheia) Fim_se Fim //Sub-rotina consultarInicio tem os argumentos _lista, _k, _fim passados por valor. Os argumentos sinal e valor so passados por referncia pois, _sinal indicar se encontrou o topo e _valor retorna o valor do topo. Sub-rotina consultarInicio(_lista : TipoLista; _k, _fim : Inteiro; ref _sinal : Lgico; ref _valor : TipoDado) Inicio Se _k > 0 e _k <= _fim Ento _valor _lista[_k] _sinal .V. Seno _sinal .F. Fim_se Fim //Sub-rotina alterarInicio tem os argumentos _k, _fim e _valor passados por valor. Os argumentos _lista e _sinal so passados por referncia pois, _sinal indicar se alterou o topo e _lista ter um elemento alterado. Sub-rotina alterarInicio(ref _lista : TipoLista; _k, _fim : Inteiro; ref _sinal : Lgico; _valor : TipoDado) Inicio

29

Se _k > 0 e _k <= _fim Ento _lista[_k] _valor _sinal .V. Seno _sinal .F. Fim_se Fim //Sub-rotina desenfileirar ou dequeue tem os argumento _k passado por valor. Os argumentos _lista, _fim e _sinal so passados por referncia pois, _sinal indicar se desempilhou, _fim ser decrementado em 1 e _lista ter um elemento desempilhado. Sub-rotina desenfileirar (ref _lista: TipoLista; _k : Inteiro; ref _fim : Inteiro; ref _sinal : Lgico) Variveis i : Inteiro Inicio Se _k > 0 e _k <= _fim Ento // Usa o lao, pois exclui sempre do inicio. Para i de _k at _fim passo +1 faa _lista[i] _lista[i+1] Fim_para _fim _fim - 1 _sinal .V. Seno _sinal .F. Fim_se Fim

30

7. Implementaes por Encadeamento


7.1 Lista Simplesmente Encadeada 7.1.1 Definio
Este tipo de lista o mais simples e segue as seguintes regras: deve existir um ponteiro que aponte para o primeiro elemento da lista (incio da lista); cada elemento, ou n, da lista aponta para o prximo sucessivamente (da o nome listas encadeadas) o ltimo elemento deve apontar para NULO, indicando o final da lista.

7.1.2 Aplicao
As listas simplesmente encadeadas so utilizadas quando h necessidade de criar vetores com tamanho varivel (dinmico), sua limitao, somente permitir, o caminhamento unidirecional na lista, pois, como as referncias iniciam no primeiro elemento da lista e seguem unidirecionalmente at o ltimo elemento, no possvel regressar no caminhamento atravs da lista. Mesmo com esta limitao, as listas simplesmente encadeadas so largamente utilizadas, pela sua simplicidade de implementao fornecendo um bom ndice entre custo/benefcio, na gerencia, em memria, de conjuntos de dados no muito extensos.

7.1.3 Componente da Lista


dado proximo

Figura 9 - Componente da Lista

7.1.4 Esquema da Representao


Inicio

dado

proximo

dado

proximo

dado

proximo

Figura 10 - Esquema da Representao

31

7.1.5 Operaes Bsicas


Como toda estrutura de armazenamento de dados, as listas simplesmente encadeadas devem suportar as operaes de cadastro das informaes. Uma particularidade das listas o fato de apresentarem uma pequena variao no cdigo de incluso e excluso. De acordo com o local onde o novo elemento dever ser inserido (no incio, no meio ou no fim). E ainda assim, est variao pode ocorrer de acordo com os mecanismos de controle utilizados na gerencia da lista, tais como, utilizao de um nico ponteiro apontando para o inicio da lista, ou dois ponteiros, um para o incio e outro para o final.

7.1.6 Implementao Lista Simplesmente Encadeada


Algoritmo Programa_Lista_Simplesmente_Encadeada Tipo TipoDado : Inteiro No : Registro Dado : TipoDado Proximo : No Fim_registro Variveis inicio opcao , K val

: No : Inteiro : TipoDado

Inicio inicio nulo //Inicializa a lista opcao -1 // Menu para chamada das operaes de uma lista Enquanto opcao <> 10 faa Escreva( 1 Inserir Inicio 2 Inserir K 3- Inserir Fim 4 Remover Inicio 5 Remover K 6 Remover Fim 7 - Alterar K 8 Acessar K 9 Listar 10 Sair) Leia(opcao) Se opcao = 1 ento Escreva(Qual o valor a inserir no inicio ? ) Leia val inserirInicio(inicio, val) //K = 1 Seno Se opcao = 2 ento Escreva(Qual a posio a ser inserida? ) Leia K Escreva(Qual o valor a inserir na posio K? ) Leia val inserirK(inicio,K, val) //K lido Seno Se opcao = 3 ento Escreva(Qual o valor a inserir no fim? ) Leia val inserirFim(inicio, val) //K = N Seno Se opcao = 4 ento removerInicio(inicio) Seno Se opcao = 5 ento Escreva(Qual a posio a ser removida?) Leia K removerK(inicio, K) Seno Se opcao = 6 Ento

32

removerFim(inicio) Seno Se opcao = 7 Ento Escreva(Qual a posio a ser alterada? ) Leia K Escreva(Qual o novo valor? ) Leia val alterar(inicio,K,val) Seno Se opcao = 8 Ento Escreva(Qual a posio k a ser consultada? ) Leia K acessar(inicio,K) Seno Se opcao = 9 Ento listar(inicio) Fim_se //9 Fim_se //8 Fim_se //7 Fim_se //6 Fim_se //5 Fim_se //4 Fim_se // 3 Fim_se //2 Fim_se //1 Fim_enquanto Fim. //Sub-rotina inserirInicio tem o argumento _valor passado por valor com os dados de um novo n. O argumento _inicio passado por referncia pois ser modificado quando novo n for inserido no incio. Sub-rotina inserirInicio(ref _inicio : No; _valor : TipoDado) Variveis novo : No Inicio Aloca(novo) // obtm espao para um novo no novo.dado _valor // armazena valor no novo no // garante que o n ter o prximo a partir do incio anterior novo.proximo _inicio _inicio novo // atribui o novo incio Escreva (Elemento inserido com sucesso) Fim //Sub-rotina inserirK tem o argumento _k e valor passado por valor onde _valor possui os dados de um novo n e _k a posio de insero. O argumento _inicio passado por referncia pois ser modificado quando novo n for inserido na posio _k. Sub-rotina inserirK(ref _inicio : No; _k : Inteiro; _valor : TipoDado) Variveis atual, anterior, novo : No cont : Inteiro Inicio Aloca(novo) // obtm espao para um novo no novo.dado _valor // armazena valor no novo no novo.proximo nulo Se _k > 0 ento Se _k > 1 ento //no localiza o ltimo no atual _inicio anteiror nulo cont 1

33

Enquanto atual <> nulo e cont <> _k faa anterior atual atual atual.proximo cont cont + 1 Fim_enquanto Se anterior <> nulo ento novo.proximo anterior.proximo anterior.proximo novo Escreva (Elemento inserido com sucesso) Seno Escreva (Elemento no inserido) Fim_se Seno novo.proximo _inicio _inicio novo Escreva (Elemento inserido com sucesso) Fim_se Seno Escreva (Elemento no inserido) Fim_se Fim //Sub-rotina inserirFim tem o argumento _valor passado por valor com os dados de um novo n. O argumento _inicio passado por referncia pois ser modificado quando novo n for inserido no fim. Sub-rotina inserirFim(ref _inicio : ref No; _valor : TipoDado) Variveis atual, novo : No Inicio Aloca(novo) // obtm espao para um novo no novo.dado _valor // armazena valor no novo no novo.proximo nulo // garante que o ltimo no da lista ter nulo Se _inicio = nulo ento //lista vazia? _inicio novo // sim, inicializa a lista Seno //no localiza o ltimo no atual _inicio Enquanto atual.proximo <> nulo faa atual atual.proximo Fim_enquanto atual.proximo novo Fim_se Escreva (Elemento inserido com sucesso) Fim //Sub-rotina removerInicio tem o argumento _inicio passado por referncia pois ser modificado quando novo n for excludo do incio. Sub-rotina removerInicio(ref _inicio : No) Variveis temp : No Inicio Se _inicio <> nulo ento temp _inicio // // guarda ponteiro do elemento a ser excludo // garante que o n ter o prximo a partir do incio anterior _inicio _inicio.proximo desaloca(temp) // desaloca temp devolvendo o espao ao S.O. Escreva (Elemento removido com sucesso) Seno Escreva (Lista Vazia) Fim_se Fim

34

//Sub-rotina removerK tem o argumento _inicio passado por referncia pois ser modificado quando novo n for excludo e _k passado por valor para indicar a posio do n a ser excludo. Sub-rotina removerK(ref _inicio : No, _k : Inteiro) Variveis atual, temp : No cont : Inteiro Inicio Se _inicio <> nulo ento //lista no vazia Se _inicio.proximo <> nulo e _k > 1 ento //com mais de um n // localiza o ltimo no atual _inicio anterior nulo cont 1 // procura o ltimo no Enquanto atual.proximo <> nulo e cont <> _k faa anterior atual // guarda o no anterior ao ltimo atual atual.proximo cont cont + 1 Fim_enquanto temp atual// guarda ponteiro do elemento a ser excludo // ou anterior.proximo nulo // Pula o elemento a excluir anterior.proximo atual.proximo Seno // com somente um no e _k = 1 Se _k = 1 ento temp _inicio // guarda ponteiro do elemento a ser excludo // ou _inicio nulo // Pula o elemento a excluir _inicio _inicio.proximo Fim_se Fim_se desaloca(temp) // desaloca temp devolvendo o espao ao S.O. Escreva (Elemento removido com sucesso) Seno Escreva (Lista Vazia) Fim_se Fim //Sub-rotina removerFim tem o argumento _inicio passado por referncia pois ser modificado quando novo n for excludo do fim. Sub-rotina removerFim (ref _inicio : No) Variveis anterior,atual, temp : No Inicio Se _inicio <> nulo ento //lista no vazia Se _inicio.proximo <> nulo ento //com mais de um n // localiza o ltimo no atual _inicio anterior nulo Enquanto atual.proximo <> nulo faa // procura o ltimo no anterior atual // guarda o no anterior ao ltimo atual atual.proximo Fim_enquanto temp atual// guarda ponteiro do elemento a ser excludo anterior.proximo atual.proximo // ou anterior.proximo nulo Seno // com somente um no temp _inicio // guarda ponteiro do elemento a ser excludo _inicio _inicio.proximo // ou _inicio nulo Fim_se desaloca(temp) // desaloca temp devolvendo o espao ao S.O. Escreva (Elemento removido com sucesso) Seno

35

Escreva (Lista Vazia) Fim_se Fim //Sub-rotina alterar tem os argumentos _inicio, _valor, _k passados por valor. O argumento _inicio indica onde comea a lista, _k a posio a ser alterada e _valor o novo valor para a posio. Sub-rotina alterar(_inicio: No; _k : Inteiro; _valor : TipoDado) Variveis atual : No cont : Inteiro Inicio Se _inicio <> nulo ento atual _inicio cont 1 Enquanto atual.proximo <> nulo e cont <> _k faa atual atual.proximo cont cont + 1 Fim_enquanto Se cont = _k ento atual.dado _valor Escreva (Elemento alterado com sucesso) Seno Escreva (Elemento no alterado) Fim_se Seno Escreva (Lista Vazia) Fim_se Fim //Sub-rotina acessar tem os argumentos _inicio, _k argumento _inicio indica onde comea a lista, _k a Sub-rotina acessar(_inicio: No; _k : Inteiro) Variveis atual : No cont : Inteiro Inicio Se _inicio <> nulo ento atual _inicio cont 1 Enquanto atual.proximo <> nulo e cont <> _k atual atual.proximo cont cont + 1 Fim_enquanto Se cont = _k ento Escreva (O Valor da posio + _k + e Seno Escreva (Elemento no encontrado) Fim_se Seno Escreva (Lista Vazia) Fim_se Fim passados por valor. O posio a ser acessada.

faa

: + atual.dado)

//Sub-rotina listar tem o argumento _inicio que indica onde comea a lista. Sub-rotina listar(_inicio: No) Variveis atual : No cont : Inteiro Inicio Se _inicio <> nulo ento

36

atual _inicio cont 0 Enquanto atual <> nulo faa cont cont + 1 Escreva (O Valor da posio + cont + e : + atual.dado) atual atual.proximo Fim_enquanto Seno Escreva (Lista Vazia) Fim_se Fim

37

7.2 Lista Simplesmente Encadeada com Descritor


Com o objetivo de facilitar o acesso ao ltimo n da lista, podemos utilizar uma segunda varivel do tipo referncia a n, para enderear o ltimo n. Chamaremos est varivel de fim conforme indicado na figura abaixo.
inicio

fim
d ado proximo d ado proximo

d ado

proximo

Figura 11 - Lista Simplesmente Encadeada com Descritor

Podemos ento simplificar os dois endereamentos reunindo em um nico elemento. A este elemento que rene as referncias ao incio e ao fim da lista damos a denominao de n descritor ou lder da lista. O acesso aos elementos da lista ser sempre efetuado atravs do seu descritor. O n descritor de uma lista pode conter outras informaes sobre a lista, a critrio do projetista, tais como: quantidade de ns da lista, descrio dos dados contidos nos ns, etc. A figura abaixo mostra esquematicamente uma lista encadeada com n descritor, no qual foi includo um campo que indica a quantidade de ns existentes na lista. desc
inicio qtde fim

dado

proximo

dado

proximo

dado

proximo

Figura 12 - Descritor com mais campos

Uma variao pode ser feita na lista com descritor onde o descritor pode ser apontado.

38

desc

inicio

qtde

fim

dado

proximo

dado

proximo

dado

proximo

Figura 13 - Descritor apontado

7.2.1 Implementao Lista Simplesmente Encadeada com Descritor


Algoritmo Programa_Lista_Simplesmente_Encadeada_Descritor Tipo TipoDado : Inteiro No : Registro dado : TipoDado proximo : No Fim_registro Descritor : Registro inicio : No qtde : Inteiro fim : No Fim_registro Variveis desc opcao , K val

: Descritor : Inteiro : TipoDado

Inicio Inicializa(desc) //Inicializa o descritor opcao -1 // Menu para chamada das operaes de uma lista Enquanto opcao <> 10 faa Escreva( 1 Inserir Inicio 2 Inserir K 3- Inserir Fim 4 Remover Inicio 5 Remover K 6 - Remover Fim 7 - Alterar K 8 Acessar K 9 Listar 10 Sair) Leia(opcao) Se opcao = 1 ento Escreva(Qual o valor a inserir no inicio ? ) Leia val inserirInicio(desc, val) //K = 1 Seno Se opcao = 2 ento Escreva(Qual a posio a ser inserida? ) Leia K Escreva(Qual o valor a inserir na posio K? ) Leia val

39

inserirK(desc,K, val) //K lido Seno Se opcao = 3 ento Escreva(Qual o valor a inserir no fim? ) Leia val inserirFim(desc, val) //K = N Seno Se opcao = 4 ento removerInicio(desc) Seno Se opcao = 5 ento Escreva(Qual a posio a ser removida? ) Leia K removerK(desc, K) Seno Se opcao = 6 Ento removerFim(desc) Seno Se opcao = 7 Ento Escreva(Qual a posio a ser alterada? ) Leia K Escreva(Qual o novo valor? ) Leia val alterar(lista,K,val) Seno Se opcao = 8 Ento Escreva(Qual a posio k a ser consultada? ) Leia K acessar(desc,K) Seno Se opcao = 9 Ento listar(desc) Fim_se //9 Fim_se //8 Fim_se //7 Fim_se //6 Fim_se //5 Fim_se //4 Fim_se // 3 Fim_se //2 Fim_se //1 Fim_enquanto Fim. //Sub-rotina inicializa possui o argumento _desc que passado por referncia, pois, ser modificado para inicializar a lista. Sub-rotina inicializa(ref _desc : No) Inicio _desc.inicio nulo _desc.qtde 0 _desc.fim nulo Fim //Sub-rotina inserirInicio tem o argumento _valor passado por valor com os dados de um novo n. O argumento _desc passado por referncia pois ser modificado quando novo n for inserido no incio. Sub-rotina inserirInicio(ref _desc : Descritor; _valor : TipoDado) Variveis novo : No Inicio Aloca(novo) // obtm espao para um novo no

40

novo.dado _valor // armazena valor no novo no // garante que o n ter o prximo a partir do incio anterior novo.proximo _desc.inicio _desc.inicio novo // atribui o novo incio _desc.qtde _desc.qtde + 1 //incrementa a qtde de ns // se a lista esta vazia Se _desc.fim = nulo ento _desc.fim novo // o primeiro elemento primeiro e ultimo Fim_se Escreva (Elemento inserido com sucesso) Fim //Sub-rotina inserirK tem o argumento _k e _valor passado por valor onde _valor possui os dados de um novo n e _k a posio de insero. O argumento _desc passado por referncia pois ser modificado quando novo n for inserido um n. Sub-rotina inserirK(ref _desc : Descritor; _k : Inteiro; _valor : TipoDado) Variveis atual, anterior, novo : No cont : Inteiro Inicio Aloca(novo) // obtm espao para um novo no novo.dado _valor // armazena valor no novo no novo.proximo nulo Se _k > 0 ento Se _k > 1 ento //no localiza o ltimo no atual _desc.inicio anteiror nulo cont 1 Enquanto atual <> nulo e cont <> _k faa anterior atual atual atual.proximo cont cont + 1 Fim_enquanto Se anterior <> nulo ento novo.proximo anterior.proximo _desc.qtde _desc.qtde + 1 //incrementa a qtde de ns se anterior.proximo = nulo ento _desc.fim novo Fim_se anterior.proximo novo Escreva (Elemento inserido com sucesso) Seno Escreva (Elemento no inserido) Fim_se Seno novo.proximo _desc.inicio _desc.inicio novo _desc.qtde _desc.qtde + 1 //incrementa a qtde de ns Se desc.fim = nulo ento _desc.fim novo Fim_se Escreva (Elemento inserido com sucesso) Fim_se Seno Escreva (Elemento no inserido) Fim_se Fim

41

//Sub-rotina inserirFim tem o argumento _valor passado por valor com os dados de um novo n. O argumento _desc passado por referncia, pois ser modificado quando novo n for inserido no fim. Sub-rotina inserirFim(ref _desc : Descritor; _valor : TipoDado) Variveis atual, novo : No Inicio Aloca(novo) // obtm espao para um novo no novo.dado _valor // armazena valor no novo no novo.proximo nulo // garante que o ltimo no da lista ter nulo Se _desc.inicio = nulo ento //lista vazia? _desc.inicio novo Seno _desc.fim.proximo novo Fim_se _desc.qtde _desc.qtde + 1 //incrementa a qtde de ns _desc.fim novo //modifica o fim Escreva (Elemento inserido com sucesso) Fim //Sub-rotina removerInicio tem o argumento _desc passado por referncia pois ser modificado quando novo n for excludo do incio. Sub-rotina removerInicio(ref _desc: Descritor) Variveis temp : No Inicio Se _desc.inicio <> nulo ento temp _desc.inicio // guarda ponteiro do elemento a ser excludo // garante que o incio ter o prximo a partir do prximo // apontado pelo incio _desc.inicio _desc.inicio.proximo _desc.qtde _desc.qtde 1 //decremento a qtde de ns Se _desc.inicio = nulo ento _desc.fim _desc.inicio // ou _desc.fim nulo Fim_se desaloca(temp) // desaloca temp devolvendo o espao ao S.O. Escreva (Elemento removido com sucesso) Seno Escreva (Lista Vazia) Fim_se Fim //Sub-rotina removerK tem o argumento _desc passado por referncia pois ser modificado quando novo n for excludo e _k passado por valor para indicar a posio do n a ser excludo. Sub-rotina removerK(ref _desc: Descritor, _k : Inteiro) Variveis anterior, atual, temp : No Inicio Se _desc.inicio <> nulo ento //lista no vazia Se _desc.inicio.proximo <> nulo e _k > 1 ento //com mais de um n // localiza o ltimo no atual _desc.inicio anterior nulo cont 1 // procura o ltimo no Enquanto atual.proximo <> nulo e cont <> _k faa anterior atual // guarda o no anterior ao ltimo atual atual.proximo cont cont + 1 Fim_enquanto

42

temp atual// guarda ponteiro do elemento a ser excludo //Pula o elemento a excluir anterior.proximo atual.proximo // ou anterior.proximo nulo _desc.qtde _desc.qtde - 1//decremento a qtde de ns Se anterior.proximo = nulo ento _desc.fim anterior Fim_se Seno // com somente um no e _k = 1 Se _k = 1 ento temp _desc.inicio // guarda ponteiro do elemento a ser excludo _desc.inicio _desc.inicio.proximo // Pula o elemento a excluir _desc.qtde _desc.qtde - 1//decrementa a qtde de ns Se _desc.inicio = nulo ento _desc.fim _desc.inicio Fim_se Fim_se Fim_se desaloca(temp) // desaloca temp devolvendo o espao ao S.O. Escreva (Elemento removido com sucesso) Seno Escreva (Lista Vazia) Fim_se Fim //Sub-rotina removerFim tem o argumento _desc passado por referncia pois ser modificado quando novo n for excludo do fim. Sub-rotina removerFim (ref _desc: Descritor) Variveis anterior, atual, temp : No Inicio Se _desc.inicio <> nulo ento //lista no vazia Se _desc.inicio.proximo <> nulo ento //com mais de um n // localiza o ltimo no atual _desc.inicio anterior nulo Enquanto atual.proximo <> nulo faa // procura o ltimo no anterior atual // guarda o no anterior ao ltimo atual atual.proximo //avana para o prximo n Fim_enquanto temp atual// guarda ponteiro do elemento a ser excludo anterior.proximo atual.proximo // ou anterior.proximo nulo _desc.fim anterior Seno // com somente um no temp _desc.inicio // guarda ponteiro do elemento a ser excludo _desc.inicio _desc.inicio.proximo // ou _desc.inicio nulo _desc.fim _desc.inicio Fim_se _desc.qtde _desc.qtde 1 //decremento a qtde de ns desaloca(temp) // desaloca temp devolvendo o espao ao S.O. Escreva (Elemento removido com sucesso) Seno Escreva (Lista Vazia) Fim_se Fim //Sub-rotina alterar tem os argumentos _desc, _valor, _k passados por valor. O argumento _desc indica onde comea a lista, _k a posio a ser alterada e _valor o novo valor para a posio. Sub-rotina alterar(_desc: Descritor; _k : Inteiro; _valor : TipoDado) Variveis atual : No

43

cont : Inteiro Inicio Se _desc.inicio <> nulo ento atual _desc.inicio cont 1 Enquanto atual.proximo <> nulo e cont <> _k faa atual atual.proximo cont cont + 1 Fim_enquanto Se cont = _k ento atual.dado _valor Escreva (Elemento alterado com sucesso) Seno Escreva (Elemento no alterado) Fim_se Seno Escreva (Lista Vazia) Fim_se Fim //Sub-rotina acessar tem os argumentos _desc, _k passados por valor. O argumento _desc indica onde comea a lista, _k a posio a ser acessada. Sub-rotina acessar(_desc: Descritor; _k : Inteiro) Variveis atual : No cont : Inteiro Inicio Se _desc.inicio <> nulo ento atual _desc.inicio cont 1 Enquanto atual.proximo <> nulo e cont <> _k faa atual atual.proximo cont cont + 1 Fim_enquanto Se cont = _k ento Escreva (O Valor da posio + _k + e : + atual.dado) Seno Escreva (Elemento no encontrado) Fim_se Seno Escreva (Lista Vazia) Fim_se Fim //Sub-rotina listar tem o argumento _desc passado por valor que indica onde comea a lista. Sub-rotina listar(_desc: Descritor) Variveis atual : No cont : Inteiro Inicio Se _desc.inicio <> nulo ento atual _desc.inicio cont 0 Enquanto atual <> nulo faa cont cont + 1 Escreva (O Valor da posio + cont + e : + atual.dado) atual atual.proximo Fim_enquanto Escreva (Existe + desc.qtde + elementos) Seno

44

Escreva (Lista Vazia) Fim_se Fim

45

7.3 Lista Circular Encadeada 7.3.1 Definio


Algumas listas necessitam representar conjuntos cclicos. Por exemplo, as arestas que delimitam uma face podem ser agrupadas por uma estrutura circular. Para esses casos, podemos usar listas circulares. Em uma lista circular, o ltimo elemento tem como prximo o primeiro elemento da lista, o que forma um ciclo. A rigor, nesse caso, no faz sentido falar em primeiro ou ltimo elemento. A lista pode ser representada por um ponteiro para um elemento inicial qualquer da lista. A figura abaixo ilustra o arranjo da memria para representao de uma lista circular. desc
inicio qtde fim

dado

proximo

dado

proximo

dado

proximo

Figura 14 - Lista Circular

Para percorrer os elementos de uma lista circular, visitamos todos os elementos a partir do ponteiro do elemento inicial at alcanar novamente esse mesmo elemento. Devemos salientar que o caso no qual a lista vazia ainda deve ser tratado ( se a lista vazia, o ponteiro para o elemento inicial vale nulo. Utilizar um lista simplesmente encadeada com descritor facilita a ligao das extremidades.

7.3.2 Implementao Lista Encadeada Circular


Algoritmo Programa_Lista_Circular_Encadeada Tipo TipoDado : Inteiro No : Registro Dado : TipoDado Proximo : No Fim_registro Descritor : Registro inicio : No qtde : Inteiro fim : No Fim_registro Variveis desc opcao , K val

: Descritor : Inteiro : TipoDado

46

Inicio Inicializa(desc) //Inicializa o descritor opcao -1 // Menu para chamada das operaes de uma lista Enquanto opcao <> 10 faa Escreva( 1 Inserir Inicio 2- Inserir Fim 3 Remover Inicio 4 - Remover Fim 5 - Alterar K 6 Acessar K 7 Listar 8 Sair) Leia(opcao) Se opcao = 1 ento Escreva(Qual o valor a inserir no inicio ? ) Leia val inserirInicio(desc, val) //K = 1 Seno Se opcao = 2 ento Escreva(Qual o valor a inserir no fim? ) Leia val inserirFim(desc, val) //K = N Seno Se opcao = 3 ento removerInicio(desc) Seno Se opcao = 4 ento removerFim(desc) Seno Se opcao = 5 Ento Escreva(Qual a posio a ser alterada? ) Leia K Escreva(Qual o novo valor? ) Leia val alterar(lista,K,val) Seno Se opcao = 6 Ento Escreva(Qual a posio k a ser consultada? ) Leia K acessar(desc,K) Seno Se opcao = 7 Ento listar(desc) Fim_se //7 Fim_se //6 Fim_se //5 Fim_se //4 Fim_se //3 Fim_se //2 Fim_se // 1 Fim_enquanto Fim. //Sub-rotina inicializa possui o argumento _desc que passado por referncia, pois ser modificado para inicializar a lista. Sub-rotina inicializa(ref _desc : No) Inicio _desc.inicio nulo _desc.qtde 0 _desc.fim nulo Fim //Sub-rotina inserirInicio tem o argumento _valor passado por valor com os dados de um novo n. O argumento _desc passado por referncia pois ser modificado quando novo n for inserido no incio.

47

Sub-rotina inserirInicio(ref _desc : Descritor; _valor : TipoDado) Variveis novo : No Inicio Aloca(novo) // obtm espao para um novo no novo.dado _valor // armazena valor no novo no // garante que o n ter o prximo a partir do incio anterior novo.proximo _desc.inicio _desc.inicio novo // atribui o novo incio _desc.qtde _desc.qtde + 1 //incrementa a qtde de ns // se a lista esta vazia o primeiro elemento e primeiro e ultimo Se _desc.fim = nulo ento _desc.fim novo Fim_se _desc.fim.proximo novo //Liga o fim ao novo inicio Escreva (Elemento inserido com sucesso) Fim //Sub-rotina inserirFim tem o argumento _valor passado por valor com os dados de um novo n. O argumento _desc passado por referncia pois ser modificado quando novo n for inserido no fim. Sub-rotina inserirFim(ref _desc : Descritor; _valor : TipoDado) Variveis atual, novo : No Inicio Aloca(novo) // obtm espao para um novo no novo.dado _valor // armazena valor no novo no Se _desc.inicio = nulo ento //lista vazia? _desc.inicio novo Seno _desc.fim.proximo novo Fim_se novo.proximo _desc.inicio //Liga o inicio ao novo fim _desc.fim novo //modifica o fim _desc.qtde _desc.qtde + 1 //incrementa a qtde de ns Escreva (Elemento inserido com sucesso) Fim //Sub-rotina removerInicio tem o argumento _desc passado por referncia pois ser modificado quando novo n for excludo do incio. Sub-rotina removerInicio(ref _desc: Descritor) Variveis temp : No Inicio Se _desc.inicio <> nulo ento temp _desc.inicio // guarda ponteiro do elemento a ser excludo // garante que o incio ter o prximo a partir do prximo // apontado pelo incio _desc.inicio _desc.inicio.proximo _desc.qtde _desc.qtde 1 //decremento a qtde de ns Se _desc.inicio <> _desc.inicio.proximo ento _desc.fim.proximo _desc.inicio Seno _desc.inicio nulo Fim_se Se _desc.inicio = nulo ento // Inicio e fim so iguais _desc.fim _desc.inicio Fim_se desaloca(temp) // desaloca temp devolvendo o espao ao S.O. Escreva (Elemento removido com sucesso) Seno

48

Escreva (Lista Vazia) Fim_se Fim //Sub-rotina removerFim tem o argumento _desc passado por referncia pois ser modificado quando novo n for excludo do fim. Sub-rotina removerFim (ref _desc: Descritor) Variveis anterior, atual, temp : No Inicio Se _desc.inicio <> nulo ento //lista no vazia Se _desc.inicio.proximo <> _desc.inicio ento //com mais de um n // localiza o ltimo no atual _desc.inicio anterior nulo Repita anterior atual // guarda o no anterior ao ltimo atual atual.proximo //avana para o prximo n At que atual.proximo = _desc.inicio // procura o ltimo no temp atual// guarda ponteiro do elemento a ser excludo anterior.proximo atual.proximo // ou anterior.proximo nulo _desc.fim anterior Seno // com somente um no temp _desc.inicio // guarda ponteiro do elemento a ser excludo _desc.inicio nulo _desc.fim _desc.inicio Fim_se _desc.qtde _desc.qtde 1 //decremento a qtde de ns desaloca(temp) // desaloca temp devolvendo o espao ao S.O. Escreva (Elemento removido com sucesso) Seno Escreva (Lista Vazia) Fim_se Fim //Sub-rotina alterar tem os argumentos _desc, _valor, _k passados por valor. O argumento _desc indica onde comea a lista, _k a posio a ser alterada e _valor o novo valor para a posio. Sub-rotina alterar(_desc: Descritor; _k : Inteiro; _valor : TipoDado) Variveis atual : No cont : Inteiro Inicio Se _desc.inicio <> nulo ento atual _desc.inicio cont 1 Enquanto atual.proximo <> nulo e cont <> _k faa atual atual.proximo cont cont + 1 Fim_enquanto Se cont = _k ento atual.dado _valor Escreva (Elemento alterado com sucesso) Seno Escreva (Elemento no alterado) Fim_se Seno Escreva (Lista Vazia) Fim_se Fim

49

//Sub-rotina acessar tem os argumentos _desc, _k passados por valor. O argumento _desc indica onde comea a lista, _k a posio a ser acessada. Sub-rotina acessar(_desc: Descritor; _k : Inteiro) Variveis atual : No cont : Inteiro Inicio Se _desc.inicio <> nulo ento atual _desc.inicio cont 1 Enquanto atual.proximo <> nulo e cont <> _k faa atual atual.proximo cont cont + 1 Fim_enquanto Se cont = _k ento Escreva (O Valor da posio + _k + e : + atual.dado) Seno Escreva (Elemento no encontrado) Fim_se Seno Escreva (Lista Vazia) Fim_se Fim //Sub-rotina listar tem os argumentos _desc passado por valor que indica onde comea a lista. Sub-rotina listar(_desc: Descritor) Variveis atual : No cont : Inteiro Inicio Se _desc.inicio <> nulo ento atual _desc.inicio cont 0 Repita cont cont + 1 Escreva (O Valor da posio + cont + e : + atual.dado) atual atual.proximo At que atual = _desc.inicio Escreva (Existe + desc.qtde + elementos) Seno Escreva (Lista Vazia) Fim_se Fim

50

7.4 Lista Duplamente Encadeada 7.4.1 Definio


uma lista encadeada, onde cada elemento contm um ponteiro para o n anterior e um ponteiro para o n posterior, permitindo o caminhamento nos dois sentidos da lista, diferentemente, da lista simplesmente encadeada, que s permitia em um nico sentido.

7.4.2 Aplicao
Aplicao das listas duplamente encadeadas semelhante as listas simplesmente encadeadas, mas aquela mais apropriada, quando h a necessidade de caminhamento em ambos os sentidos, isso faz com que, novas sub-rotinas sejam utilizadas nas listas duplamente encadeadas, tais como : Anterior, Posterior.

7.4.3 Componente da Lista


anterior dado proximo

Figura 15 - Componente Lista Duplamente Encadeada

7.4.4 Esquema da Representao


inicio

Figura 16 - Esquema Lista Duplamente Encadeada

51

7.4.5 Implementao Lista Duplamente Encadeada


Algoritmo Programa_Lista_Duplamente_Encadeada Tipo TipoDado : Inteiro No : Registro Anterior : No Dado : TipoDado Proximo : No Fim_registro Variveis inicio opcao , K val

: No : Inteiro : TipoDado

Inicio inicio nulo //Inicializa a lista opcao -1 // Menu para chamada das operaes de uma lista Enquanto opcao <> 11 faa Escreva( 1 Inserir Inicio 2 Inserir K 3- Inserir Fim 4 Remover Inicio 5 Remover K 6- Remover Fim 7 - Alterar K 8 Acessar K 9 Listar Asc 10 Lista Desc 11 Sair) Leia(opcao) Se opcao = 1 ento Escreva(Qual o valor a inserir no inicio ? ) Leia val inserirInicio(inicio, val) //K = 1 Seno Se opcao = 2 ento Escreva(Qual a posio a ser inserida? ) Leia K Escreva(Qual o valor a inserir na posio K? ) Leia val inserirK(inicio,K, val) //K lido Seno Se opcao = 3 ento Escreva(Qual o valor a inserir no fim? ) Leia val inserirFim(inicio, val) //K = N Seno Se opcao = 4 ento removerInicio(inicio) Seno Se opcao = 5 ento Escreva(Qual a posio a ser removida? ) Leia K removerK(inicio, K) Seno Se opcao = 6 Ento removerFim(inicio) Seno Se opcao = 7 Ento Escreva(Qual a posio a ser alterada? ) Leia K Escreva(Qual o novo valor? ) Leia val alterar(inicio,K,val) Seno

52

Se opcao = 8 Ento Escreva(Qual a posio k a ser consultada? ) Leia K acessar(inicio,K) Seno Se opcao = 9 Ento listarAsc(inicio) Seno Se opcao = 10 Ento listarDesc(inicio) Fim_se //10 Fim_se //9 Fim_se //8 Fim_se //7 Fim_se //6 Fim_se //5 Fim_se //4 Fim_se // 3 Fim_se //2 Fim_se //1 Fim_enquanto Fim. //Sub-rotina inserirInicio tem o argumento _valor passado por valor com os dados de um novo n. O argumento _inicio passado por referncia pois ser modificado quando novo n for inserido no incio. Sub-rotina inserirInicio(ref _inicio : No; _valor : TipoDado) Variveis novo : No Inicio Aloca(novo) // obtm espao para um novo no novo.dado _valor // armazena valor no novo no // garante que o n no ter ningum no posio anterior novo.anterior nulo // garante que o n ter o prximo a partir do incio anterior novo.proximo inicio Se _inicio <> nulo ento _inicio.anterior novo Fim_se _inicio novo // atribui o novo incio Escreva (Elemento inserido com sucesso) Fim //Sub-rotina inserirK tem o argumento _k e valor passado por possui os dados de um novo n e _k a posio de insero. O _inicio passado por referncia pois ser modificado quando inserido um n. Sub-rotina inserirK(ref _inicio : No; _k : Inteiro; _valor Variveis atual, anterior, novo : No cont : Inteiro Inicio Aloca(novo) // obtm espao para um novo no novo.dado _valor // armazena valor no novo no novo.anterior nulo novo.proximo nulo Se _k > 0 ento Se _k > 1 ento atual _inicio anteiror nulo cont 1 valor onde valor argumento novo n for : TipoDado)

53

Enquanto atual <> nulo e cont <> _k faa anterior atual atual atual.proximo cont cont + 1 Fim_enquanto Se anterior <> nulo ento novo.proximo anterior.proximo novo.anterior anterior Se anterior.proximo <> nulo ento anterior.proximo.anterior novo Fim_se anterior.proximo novo Escreva (Elemento inserido com sucesso) Seno Escreva (Elemento no inserido) Fim_se Seno novo.proximo _inicio Se _inicio <> nulo ento _inicio.anterior novo Fim_se _inicio novo Escreva (Elemento inserido com sucesso) Fim_se Seno Escreva (Elemento no inserido) Fim_se Fim //Sub-rotina inserirFim tem o argumento _valor passado por valor com os dados de um novo n. O argumento _inicio passado por referncia pois ser modificado quando novo n for inserido no fim. Sub-rotina inserirFim(ref _inicio : No; _valor : TipoDado) Variveis atual, novo : No Inicio Aloca(novo) // obtm espao para um novo no novo.dado _valor // armazena valor no novo no novo.proximo nulo Se _inicio = nulo ento //lista vazia? novo.anterior nulo _inicio novo // sim, inicializa a lista Escreva (Elemento inserido com sucesso) Seno //no localiza o ltimo no atual _inicio Enquanto atual.proximo <> nulo faa atual atual.proximo Fim_enquanto novo.anterior atual atual.proximo novo Escreva (Elemento inserido com sucesso) Fim_se Fim //Sub-rotina removerInicio tem o argumento _inicio passado por referncia pois ser modificado quando novo n for excludo do incio. Sub-rotina removerInicio(ref _inicio : No) Variveis temp : No Inicio

54

Se _inicio <> nulo ento temp _inicio // // guarda ponteiro do elemento a ser excludo // garante que o n ter o prximo a partir do incio anterior _inicio _inicio.proximo Se _inicio <> nulo ento _inicio.anterior nulo Fim_se desaloca(temp) // desaloca temp devolvendo o espao ao S.O. Escreva (Elemento removido com sucesso) Seno Escreva (Lista Vazia) Fim_se Fim //Sub-rotina removerK tem o argumento _inicio passado por referncia pois ser modificado quando novo n for excludo e _k passado por valor para indicar a posio do n a ser excludo. Sub-rotina removerK(ref _inicio : No; _k : Inteiro) Variveis anterior,atual, temp : No Inicio Se _inicio <> nulo ento //lista no vazia Se _inicio.proximo <> nulo e _k > 1 ento //com mais de um n // localiza o ltimo no atual _inicio anterior nulo cont 1 // procura o ltimo no Enquanto atual.proximo <> nulo e cont <> _k faa anterior atual // guarda o no anterior ao ltimo atual atual.proximo cont cont + 1 Fim_enquanto temp atual// guarda ponteiro do elemento a ser excludo Se atual.proximo <> nulo ento atual.proximo.anterior anterior Fim_se //Pula o elemento a excluir anterior.proximo atual.proximo // ou anterior.proximo nulo Seno // com somente um no e _k = 1 Se _k = 1 ento temp _inicio // guarda ponteiro do elemento a ser excludo // Pula o elemento a excluir _inicio _inicio.proximo // ou _inicio nulo Se _inicio <> nulo ento _inicio .anterior nulo Fim_se Fim_se Fim_se desaloca(temp) // desaloca temp devolvendo o espao ao S.O. Escreva (Elemento removido com sucesso) Seno Escreva (Lista Vazia) Fim_se Fim //Sub-rotina removerFim tem o argumento _inicio passado por referncia pois ser modificado quando novo n for excludo do fim. Sub-rotina removerFim (ref _inicio : No) Variveis atual, temp : No

55

Inicio Se _inicio <> nulo ento //lista no vazia Se _inicio.proximo <> nulo ento //com mais de um n // localiza o ltimo no atual _inicio Enquanto atual.proximo <> nulo faa // procura o ltimo no atual atual.proximo Fim_enquanto temp atual// guarda ponteiro do elemento a ser excludo atual.anterior.proximo atual.proximo //ou atual.anterior.proximo nulo Seno // com somente um no temp _inicio // guarda ponteiro do elemento a ser excludo _inicio _inicio.proximo // ou _inicio nulo Fim_se desaloca(temp) // desaloca temp devolvendo o espao ao S.O. Escreva (Elemento removido com sucesso) Seno Escreva (Lista Vazia) Fim_se Fim //Sub-rotina alterar tem os argumentos _inicio, _valor, _k passados por valor. O argumento _inicio indica onde comea a lista, _k a posio a ser alterada e _valor o novo valor para a posio. Sub-rotina alterar(_inicio: No; _k : Inteiro; _valor : TipoDado) Variveis atual : No cont : Inteiro Inicio Se _inicio <> nulo ento atual _inicio cont 1 Enquanto atual.proximo <> nulo e cont <> _k faa atual atual.proximo cont cont + 1 Fim_enquanto Se cont = _k ento atual.dado _valor Escreva (Elemento alterado com sucesso) Seno Escreva (Elemento no alterado) Fim_se Seno Escreva (Lista Vazia) Fim_se Fim //Sub-rotina acessar tem os argumentos _inicio, _k passados por valor. O argumento _inicio indica onde comea a lista, _k a posio a ser acessada. Sub-rotina acessar(_inicio: No; _k : Inteiro) Variveis atual : No cont : Inteiro Inicio Se _inicio <> nulo ento atual _inicio cont 1 Enquanto atual.proximo <> nulo e cont <> _k faa atual atual.proximo cont cont + 1

56

Fim_enquanto Se cont = _k ento Escreva (O Valor da posio + _k + e : + atual.dado) Seno Escreva (Elemento no encontrado) Fim_se Seno Escreva (Lista Vazia) Fim_se Fim //Sub-rotina listarAsc em ordem ascendente tem o argumento _inicio passado por valor que indica onde comea a lista. Sub-rotina listarAsc(_inicio: No) Variveis atual : No cont : Inteiro Inicio Se _inicio <> nulo ento atual _inicio cont 0 Enquanto atual <> nulo faa cont cont + 1 Escreva (O Valor da posio + cont + e : + atual.dado) atual atual.proximo Fim_enquanto Seno Escreva (Lista Vazia) Fim_se Fim //Sub-rotina listarDesc em ordem descendente tem o argumento _inicio passado por valor que indica onde comea a lista. Sub-rotina listarDesc(_inicio: No) Variveis atual : No cont : Inteiro Inicio Se _inicio <> nulo ento atual _inicio Enquanto atual.proximo <> nulo faa atual atual.proximo Fim_enquanto cont 0 Enquanto atual <> nulo faa cont cont + 1 Escreva (O Valor da posio + cont + e : + atual.dado) atual atual.anterior Fim_enquanto Seno Escreva (Lista Vazia) Fim_se Fim

57

7.5 Lista Duplamente Encadeada com Descritor


Os conceitos so os mesmo de lista simplesmente encadeada, muda somente o n apontado pelo descritor.
desc
inicio qtde 4 fim

Figura 17 - Esquema Lista Duplamente Encadeada com Descritor

7.5.1 Implementao Lista Duplamente Encadeada com Descritor


Algoritmo Programa_Lista_Duplamente_Encadeada_Descritor Tipo TipoDado : Inteiro No : Registro Anterior : No Dado : TipoDado Proximo : No Fim_registro Descritor : Registro inicio : No qtde : Inteiro fim : No Fim_registro Variveis Desc : Descritor opcao , K : Inteiro val : TipoDado Inicio Inicializa(desc) //Inicializa o descritor opcao -1 // Menu para chamada das operaes de uma lista Enquanto opcao <> 11 faa Escreva( 1 Inserir Inicio 2 Inserir K 3- Inserir Fim 4 Remover Inicio 5 Remover K 6 - Remover Fim 7 - Alterar K 8 Acessar K 9 Listar Asc 10 Lista Desc 11 Sair) Leia(opcao) Se opcao = 1 ento Escreva(Qual o valor a inserir no inicio ? ) Leia val inserirInicio(desc, val) //K = 1 Seno Se opcao = 2 ento Escreva(Qual a posio a ser inserida? ) Leia K Escreva(Qual o valor a inserir na posio K? ) Leia val inserirK(desc,K, val) //K lido

58

Seno Se opcao = 3 ento Escreva(Qual o valor a inserir no fim? ) Leia val inserirFim(desc, val) //K = N Seno Se opcao = 4 ento removerInicio(desc) Seno Se opcao = 5 ento Escreva(Qual a posio a ser removida? ) Leia K removerK(desc, K) Seno Se opcao = 6 Ento removerFim(desc) Seno Se opcao = 7 Ento Escreva(Qual a posio a ser alterada? ) Leia K Escreva(Qual o novo valor? ) Leia val alterar(desc,K,val) Seno Se opcao = 8 Ento Escreva(Qual a posio k a ser consultada? ) Leia K acessar(desc,K) Seno Se opcao = 9 Ento listarAsc(desc) Seno Se opcao = 10 Ento listarDesc(desc) Fim_se //10 Fim_se //9 Fim_se //8 Fim_se //7 Fim_se //6 Fim_se //5 Fim_se //4 Fim_se // 3 Fim_se //2 Fim_se //1 Fim_enquanto Fim. //Sub-rotina inicializa possui o argumento _desc que passado por referncia, pois ser modificado para inicializar a lista. Sub-rotina inicializa(ref _desc : No) Inicio _desc.inicio nulo _desc.qtde 0 _desc.fim nulo Fim //Sub-rotina inserirInicio tem o argumento _valor passado por valor com os dados de um novo n. O argumento _desc passado por referncia, pois ser modificado quando novo n for inserido no incio. Sub-rotina inserirInicio(ref _desc : Descritor; _valor : TipoDado) Variveis

59

novo : No Inicio Aloca(novo) // obtm espao para um novo no novo.dado _valor // armazena valor no novo no // garante que o n no ter ningum no posio anterior novo.anterior nulo // garante que o n ter o prximo a partir do incio anterior novo.proximo _desc.inicio //muda o anterior do primeiro elemento da lista para o novo Se _desc.inicio <> nulo ento _desc.inicio.anterior novo Fim_se _desc.inicio novo // atribui o novo incio _desc.qtde _desc.qtde + 1//incremento a qtde de ns // se a lista esta vazia o primeiro elemento e primeiro e ultimo Se _desc.fim = nulo ento _desc.fim novo Fim_se Escreva (Elemento inserido com sucesso) Fim //Sub-rotina inserirK tem o argumento _k e _valor passado por valor onde valor possui os dados de um novo n e _k a posio de insero. O argumento _desc passado por referncia pois ser modificado quando novo n for inserido na posio _k. Sub-rotina inserirK(ref _desc : Descritor; _k : Inteiro ; _valor : TipoDado) Variveis atual, anterior, novo : No cont : Inteiro Inicio Aloca(novo) // obtm espao para um novo no novo.dado _valor // armazena valor no novo no novo.anterior nulo novo.proximo nulo Se _k > 0 ento Se _k > 1 ento atual _desc.inicio anterior nulo cont 1 Enquanto atual <> nulo e cont <> _k faa anterior atual atual atual.proximo cont cont + 1 Fim_enquanto Se anterior <> nulo ento novo.proximo anterior.proximo novo.anterior anterior Se anterior.proximo <> nulo ento anterior.proximo.anterior novo Fim_se _desc.qtde _desc.qtde + 1//incremento a qtde de ns se anterior.proximo = nulo ento _desc.fim novo Fim_se anterior.proximo novo Escreva (Elemento inserido com sucesso) Seno Escreva (Elemento no inserido) Fim_se Seno novo.proximo _desc.inicio

60

Se _desc.inicio <> nulo ento _desc.inicio.anterior novo Fim_se _desc.inicio novo _desc.qtde _desc.qtde + 1//incremento a qtde de ns Se _desc.fim = nulo ento _desc.fim novo Fim_se Escreva (Elemento inserido com sucesso) Fim_se Seno Escreva (Elemento no inserido) Fim_se Fim //Sub-rotina inserirFim tem o argumento _valor passado por valor com os dados de um novo n. O argumento _desc passado por referncia, pois ser modificado quando novo n for inserido no fim. Sub-rotina inserirFim(ref _desc : Descritor; _valor : TipoDado) Variveis novo : No Inicio Aloca(novo) // obtm espao para um novo no novo.dado _valor // armazena valor no novo no novo.proximo nulo // garante que o n no ter ningum no posio prxima // garante que o n ter o anterior a partir do fim anterior novo.anterior _desc.fim //Se existe fim Se _desc.fim <> nulo ento //muda o prximo do ultimo elemento da lista para o novo _desc.fim.proximo novo Fim_se _desc.fim novo // atribui o novo fim _desc.qtde _desc.qtde + 1//incremento a qtde de ns // se a lista esta vazia Se _desc.inicio = nulo ento // o novo elemento ultimo e primeiro _desc.inicio novo Fim_se Escreva (Elemento inserido com sucesso) Fim //Sub-rotina removerInicio tem o argumento _desc passado por referncia pois ser modificado quando novo n for excludo do incio. Sub-rotina removerInicio(ref _desc : Descritor) Variveis temp : No Inicio Se _desc.inicio <> nulo ento temp _desc.inicio // guarda ponteiro do elemento a ser excludo // garante que o n ter o prximo a partir do incio anterior _desc.inicio _desc.inicio.proximo Se _desc.inicio <> nulo ento _desc.inicio.anterior nulo Fim_se _desc.qtde _desc.qtde - 1//decremento a qtde de ns Se _desc.inicio = nulo ento _desc.fim _desc.inicio // ou desc.fim nulo Fim_se desaloca(temp) // desaloca temp devolvendo o espao ao S.O.

61

Escreva (Elemento removido com sucesso) Seno Escreva (Lista Vazia) Fim_se Fim //Sub-rotina removerK tem o argumento _desc passado por referncia pois ser modificado quando novo n for excludo e _k passado por valor para indicar a posio do n a ser excludo. Sub-rotina removerK(ref _desc : Descritor; _k : Inteiro) Variveis atual, temp : No Inicio Se _desc.inicio <> nulo ento //lista no vazia Se _desc.inicio.proximo <> nulo e _k > 1 ento //com mais de um n // localiza o ltimo no atual _desc.inicio anterior nulo cont 1 // procura o ltimo no Enquanto atual.proximo <> nulo e cont <> _k faa anterior atual // guarda o no anterior ao ltimo atual atual.proximo cont cont + 1 Fim_enquanto temp atual// guarda ponteiro do elemento a ser excludo Se atual.proximo <> nulo ento atual.proximo.anterior anterior Fim_se // Pula o elemento a excluir anterior.proximo atual.proximo // ou anterior.proximo nulo _desc.qtde _desc.qtde - 1//decremento a qtde de ns Se anterior.proximo = nulo ento _desc.fim anterior Fim_se Seno // com somente um no e _k = 1 Se _k = 1 ento temp _desc.inicio // guarda ponteiro do elemento a ser excludo // Pula o elemento a excluir _desc.inicio _desc.inicio.proximo //ou inicio nulo Se _desc.inicio <> nulo ento _desc.inicio.anterior nulo Fim_se _desc.qtde _desc.qtde - 1 //decremento a qtde de ns Se _desc.inicio = nulo ento _desc.fim _desc.inicio Fim_se Fim_se Fim_se desaloca(temp) // desaloca temp devolvendo o espao ao S.O. Escreva (Elemento removido com sucesso) Seno Escreva (Lista Vazia) Fim_se Fim //Sub-rotina removerFim tem o argumento _desc passado por referncia pois ser modificado quando novo n for excludo do fim. Sub-rotina removerFim (ref _desc : Descritor) Variveis atual, temp : No

62

Inicio Se _desc.fim <> nulo ento //lista no vazia temp _desc.fim // guarda ponteiro do elemento a ser excludo // garante que o n ter o anterior a partir do fim anterior _desc.fim _desc.fim.anterior Se _desc.fim <> nulo ento _desc.fim.proximo nulo Fim_se _desc.qtde _desc.qtde - 1//decremento a qtde de ns Se _desc.fim = nulo ento _desc.inicio _desc.fim // ou _desc.inicio nulo Fim_se desaloca(temp) // desaloca temp devolvendo o espao ao S.O. Escreva (Elemento removido com sucesso) Seno Escreva (Lista Vazia) Fim_se Fim //Sub-rotina alterar tem os argumentos _desc, _valor, _k passados por valor. O argumento _desc indica onde comea a lista, _k a posio a ser alterado e _valor o novo valor para a posio. Sub-rotina alterar(_desc : Descritor; _k : Inteiro; _valor : TipoDado) Variveis atual : No cont : Inteiro Inicio Se _desc.inicio <> nulo ento atual _desc.inicio cont 1 Enquanto atual.proximo <> nulo e cont <> _k faa atual atual.proximo cont cont + 1 Fim_enquanto Se cont = _k ento atual.dado _valor Escreva (Elemento alterado com sucesso) Seno Escreva (Elemento no alterado) Fim_se Seno Escreva (Lista Vazia) Fim_se Fim //Sub-rotina acessar tem os argumentos _desc, _k passados por valor. O argumento _desc indica onde comea a lista, _k a posio a ser acessada. Sub-rotina acessar(_desc : Descritor; _k : Inteiro) Variveis atual : No cont : Inteiro Inicio Se _desc.inicio <> nulo ento atual _desc.inicio cont 1 Enquanto atual.proximo <> nulo e cont <> _k faa atual atual.proximo cont cont + 1 Fim_enquanto Se cont = _k ento Escreva (O Valor da posio + _k + e : + atual.dado)

63

Seno Escreva (Elemento no encontrado) Fim_se Seno Escreva (Lista Vazia) Fim_se Fim //Sub-rotina listarAsc em ordem ascendente tem o argumento _desc passado por valor que indica onde comea a lista. Sub-rotina listarAsc(_desc : Descritor) Variveis atual : No cont : Inteiro Inicio Se _desc.inicio <> nulo ento atual _desc.inicio cont 0 Enquanto atual <> nulo faa cont cont + 1 Escreva (O Valor da posio + cont + e : + atual.dado) atual atual.proximo Fim_enquanto Seno Escreva (Lista Vazia) Fim_se Fim //Sub-rotina listarDesc em ordem descendente tem s argumento _desc passado por valor que indica onde comea a lista. Sub-rotina listarDesc(_desc : Descritor) Variveis atual : No cont : Inteiro Inicio Se _desc.fim <> nulo ento atual _desc.fim cont 0 Enquanto atual <> nulo faa cont cont + 1 Escreva (O Valor da posio + cont + e : + atual.dado) atual atual.anterior Fim_enquanto Seno Escreva (Lista Vazia) Fim_se Fim

64

7.6 Listas Encadeadas com Disciplina de Acesso 7.6.1 Pilha com Encadeamento
Pilhas podem ser implementadas atravs de listas ligadas. A vantagem deste mtodo a flexibilidade que se consegue por causa da utilizao de listas encadeadas. Um exemplo disto que diminui muito a possibilidade de se cometer um erro de overflow, pois teoricamente no existe um limite superior para o armazenamento em lista ligada. A estrutura de dados que armazena a pilha assim tambm como o esquema de implementao da pilha utilizando-se a estrutura definida mostrado a seguir:

Figura 18 - Esquema Pilha com encadeamento

7.6.2 Implementao de Pilha com Encadeamento


Este exemplo de pilha utiliza lista simplesmente encadeada como base.
Algoritmo Programa_Pilha_Com_Lista_Simplesmente_Encadeada Tipo TipoDado : Inteiro No : Registro Dado : TipoDado Proximo : No Fim_registro Variveis inicio opcao , K val

: No : Inteiro : TipoDado

Inicio inicio nulo //Inicializa a lista opcao -1 // Menu para chamada das operaes de uma Pilha Enquanto opcao <> 6 faa Escreva( 1 Empilhar 2 Acessar Topo 3 Alterar Topo 4 Desempilhar 5 Listar Pilha 6 Sair) Leia(opcao) Se opcao = 1 ento Escreva(Qual o valor a Empilhar? )

65

Leia val empilhar(inicio, val) //K = 1 Seno Se opcao = 2 ento acessarTopo(inicio) Seno Se opcao = 3 ento Escreva(Qual o novo valor do topo? ) Leia val alterarTopo(inicio,val) Seno Se opcao = 4 ento desempilhar(inicio) Seno Se opcao = 5 ento Listar(inicio) Fim_se //5 Fim_se //4 Fim_se // 3 Fim_se //2 Fim_se //1 Fim_enquanto Fim. //Sub-rotina empilhar tem o argumento _valor passado por valor com os dados de um novo n. O argumento _inicio passado por referncia pois ser modificado quando novo n for inserido no topo. Sub-rotina empilhar(ref _inicio : No; _valor : TipoDado) Variveis novo : No Inicio Aloca(novo) // obtm espao para um novo no novo.dado _valor // armazena valor no novo no // garante que o n ter o prximo a partir do incio anterior novo.proximo _inicio _inicio novo // atribui o novo incio Escreva (Elemento empilhado com sucesso) Fim //Sub-rotina acessarTopo tem o argumento _inicio passado por valor. argumento _inicio indica onde comea a pilha. Sub-rotina acessarTopo (_inicio: No) Inicio Se _inicio <> nulo ento Escreva (O Valor do Topo : + _inicio.dado) Seno Escreva (Pilha Vazia) Fim_se Fim O

//Sub-rotina alterarTopo tem os argumentos _inicio, _valor passados por valor. O argumento _inicio indica onde comea a pilha e _valor e o novo contedo para o topo da pilha. Sub-rotina alterarTopo(_inicio: No; _valor : TipoDado) Inicio Se _inicio <> nulo ento _inicio.dado _valor Escreva (Elemento do topo alterado com sucesso) Seno Escreva (Pilha Vazia) Fim_se

66

Fim //Sub-rotina desempilhar tem o argumento _inicio passado por referncia, pois ser modificado quando novo n for excludo do topo. Sub-rotina desempilhar (ref _inicio : No) Variveis temp : No Inicio Se _inicio <> nulo ento temp _inicio // // guarda ponteiro do elemento a ser excludo // garante que o n ter o prximo a partir do incio anterior _inicio _inicio.proximo desaloca(temp) // desaloca temp devolvendo o espao ao S.O. Escreva (Elemento desempilhado com sucesso) Seno Escreva (Pilha Vazia) Fim_se Fim //Sub-rotina listar tem o argumento _inicio passado por valor que indica onde comea a pilha. Sub-rotina listar(_inicio: No) Variveis atual : No cont : Inteiro Inicio Se _inicio <> nulo ento atual _inicio cont 0 Enquanto atual <> nulo faa cont cont + 1 Escreva (O Valor da posio + cont + e : + atual.dado) atual atual.proximo Fim_enquanto Seno Escreva (Pilha Vazia) Fim_se Fim

7.6.3 Fila com Encadeamento


A estrutura que abriga a fila idntica estrutura definida para armazenar uma lista simplesmente encadeada e apresentada abaixo: O esquema de funcionamento da fila mostrado a seguir:

Figura 19 - Esquema Fila com encadeamento

67

7.6.4 Implementao de Fila com Encadeamento


Este exemplo de fila utiliza lista simplesmente encadeada com descritor como base.
Algoritmo Programa_Fila_Com_Lista_Simplesmente_Encadeada_Descritor Tipo TipoDado : Inteiro No : Registro Dado : TipoDado Proximo : No Fim_registro Descritor : Registro inicio : No qtde : Inteiro fim : No Fim_registro Variveis desc opcao , K val

: Descritor : Inteiro : TipoDado

Inicio inicializa(desc) //Inicializa o descritor opcao -1 // Menu para chamada das operaes de uma fila Enquanto opcao <> 6 faa Escreva( 1 Enfileirar 2 Consultar Inicio 3 Alterar Inicio 4 Desenfileirar 5 Listar Fila 6 Sair) Leia(opcao) Se opcao = 1 ento Escreva(Qual o valor a Enfileirar ? ) Leia val emfileirar(desc, val) Seno Se opcao = 2 ento consultarInicio(desc) Seno Se opcao = 3 ento Escreva(Qual o novo valor do inicio da fila? ) Leia val alterarInicio(desc,val) Seno Se opcao = 4 ento desemfileirar(desc) Seno Se opcao = 5 ento listar(desc) Fim_se //5 Fim_se //4 Fim_se // 3 Fim_se //2 Fim_se //1 Fim_enquanto Fim. //Sub-rotina inicializa possui o argumento _desc que passado por referncia pois ser modificado para inicializar a lista.

68

Sub-rotina inicializa(ref _desc : No) Inicio _desc.inicio nulo _desc.qtde 0 _desc.final nulo Fim //Sub-rotina enfileirar tem o argumento _valor passado por valor com os dados de um novo n. O argumento _desc passado por referncia pois ser modificado quando novo n for inserido no fim da fila. Sub-rotina enfileirar (ref _desc : Descritor; _valor : TipoDado) Variveis atual, novo : No Inicio Aloca(novo) // obtm espao para um novo no novo.dado _valor // armazena valor no novo no novo.proximo nulo // garante que o ltimo no da fila ter nulo Se _desc.inicio = nulo ento //fila vazia? _desc.inicio novo Escreva (Elemento enfileirado com sucesso) Seno _desc.fim.proximo novo Escreva (Elemento enfileirado com sucesso) Fim_se _desc.qtde _desc.qtde + 1 //incrementa a qtde de ns _desc.fim novo //modifica o fim Fim //Sub-rotina consultarInicio tem o argumento _desc passado por valor. argumento _desc indica onde comea a fila. Sub-rotina consultarInicio (_desc: Descritor) Inicio Se _desc.inicio <> nulo ento Escreva (O Valor do incio da fila e : + _desc.inicio.dado) Seno Escreva (Fila Vazia) Fim_se Fim //Sub-rotina alterarInicio tem os argumentos _desc, valor. O argumento _desc indica onde comea a fila a posio _k. Sub-rotina alterarInicio(_desc: Descritor; _valor : Inicio Se _desc.inicio <> nulo ento _desc.inicio.dado _valor Escreva (Elemento do incio da fila alterado Seno Escreva (Fila Vazia) Fim_se Fim O

_valor, _k passados por e valor o novo valor para TipoDado)

com sucesso)

//Sub-rotina desenfileirar tem o argumento _desc passado por referncia, pois ser modificado quando novo n for excludo do incio da fila. Sub-rotina desenfileirar(ref _desc: Descritor) Variveis temp : No Inicio Se _desc.inicio <> nulo ento temp _desc.inicio // guarda ponteiro do elemento a ser excludo // o n ter o prximo a partir do incio anterior

69

_desc.inicio _desc.inicio.proximo _desc.qtde _desc.qtde 1 //decremento a qtde de ns Se _desc.inicio = nulo ento _desc.fim _desc.inicio // ou _desc.fim nulo Fim_se desaloca(temp) // desaloca temp devolvendo o espao ao S.O. Escreva (Elemento desenfileirado com sucesso) Seno Escreva Fila Vazia Fim_se Fim //Sub-rotina listar tem os argumentos _desc passado por valor que indica onde comea a lista. Sub-rotina listar(_desc: Descritor) Variveis atual : No cont : Inteiro Inicio Se _desc.inicio <> nulo ento atual _desc.inicio cont 0 Enquanto atual <> nulo faa cont cont + 1 Escreva O Valor da posio + cont + e : + atual.dado atual atual.proximo Fim_enquanto Escreva Existe + _desc.qtde + elementos Seno Escreva Fila Vazia Fim_se Fim

70

8. Recursividade
8.1 Introduo
Na programao de computadores, a recurso uma tcnica que define um problema em termos de uma ou mais verses menores deste mesmo problema. Esta ferramenta pode ser utilizada sempre que for possvel expressar a soluo de um problema em funo do prprio problema. Sendo assim, um nmero infinito de clculos pode ser definido por um programa recursivo finito, ainda que este no contenha repeties explcitas (como enquanto, repita, para faa). A recurso no um conceito novo, sendo diretamente derivado das relaes de recorrncia da Matemtica. Um exemplo clssico o somatrio (A soma S dos N primeiros nmeros inteiros): Supondo N = 5; S(5) = 1+2+3+4+5 S(4) = 1+2+3+4 S(3) = 1+2+3 S(2) = 1+2 S(1) = 1 =15 =10 =6 =3 =1 -> S(5) = S(4) + 5 = 15 -> 10 + 5 = 15 -> S(4) = S(3) + 4 = 10 -> 6 + 4 = 10 -> S(3) = S(2) + 3 = 6 -> 3 + 3 = 6 -> S(2) = S(1) + 2 = 3 -> 1 + 2 = 3 -> S(1) = 1 --------------------->soluo trivial

recursiva Nota-se que o somatrio de 4 est dentro do somatrio de 5, assim como o de 3 est no de 4, o de 2 est no de 3 e assim por diante. Porm, em algum momento, necessrio se achar uma soluo definitiva para o problema, que no envolva resoluo de novos somatrios. Esta soluo definitiva aparece quando se busca a soluo para S(1), que igual a 1. Uma vez que se tem a soluo para S(1), pode-se substituir este valor na expresso S(2) = 2 + S(1) 1, e assim por diante. Com isso, para se chegar a resoluo do somatrio de 5, basta somar o somatrio de 4 mais 5.

8.2 Como codificar programas recursivos


Para se codificar programas de modo recursivo usa-se uma sub-rotina, que permite dar um nome a um comando, o qual pode chamar a si prprio. Esta chamada pode ser diretamente recursiva, quando a sub-rotina P contiver uma referncia explcita a si prpria, ou indiretamente recursiva, quando a sub-rotina P contiver uma referncia a outra sub-rotina Q, que por sua vez contm uma referncia direta ou indireta a P. Com isso, a recurso pode no ser imediatamente visvel pela inspeo do texto do programa. Todas as sub-rotinas apresentados neste texto utilizam-se de recurso direta. comum a definio de variveis locais a uma sub-rotina. Quando a mesma sub-rotina ativado recursivamente, um novo conjunto de variveis locais criado. Ainda que com os mesmos nomes, mas em posies de memria diferentes. Conflitos de nomes so evitados pela aplicao das regras de escopo dos identificadores, os quais se referem as variveis recentemente criadas. Em se tratando de sub-rotinas recursivas pode-se ocorrer um problema de terminao do programa, como um looping interminvel ou infinito. Portanto, para determinar a terminao das repeties, deve-se: 1) Definir uma funo que implica em uma condio de terminao (soluo trivial), e 2) Provar que a funo decresce a cada passo de repetio, permitindo que, eventualmente, esta soluo trivial seja atingida. Retomando o exemplo do somatrio, percebemos que existe uma funo, a qual chamada constantemente at que encontre a soluo do problema.

71

Ento temos que: S(N) = S(N 1) + N Como a soluo para S(N) pode ser encontrada a partir da soluo de S(N 1), que uma simplificao do problema, podemos continuar a diminuir o valor de N at chegarmos a uma soluo trivial, isto , se N = 1 ento S(N) = 1. Para um bom funcionamento de uma sub-rotina recursiva, ele deve conter pelo menos uma soluo trivial. Sabendo-se disto podemos refinar a regra para o clculo recursivo dos N primeiros nmeros inteiros: 1, se N = 1 S(N 1) + N, se N > 1 soluo trivial chamada recursiva

S(N) =

A partir desta regra, fica fcil se codificar o programa que implementa o somatrio. Ex:
Algoritmo RecursivoSoma Variveis n : Inteiro Sub-rotina soma( _n : Inteiro ) : Inteiro Inicio Se (_n = 1) Ento Retorne 1 Seno Retorne (_n + soma(_n 1)) Fim_se Fim Inicio Leia(n) Escreva("A soma "+ soma(n)) Fim.

72

principal n=4 soma(4)

1)soma n=3

2)soma n=2

3)soma

4)soma

n=1 4+soma(3) 3+soma(2) 2+soma(1) 0 soma(4)=10 soma(3)=6 soma(2)=3 soma(1)=1

Figura 20 - Teste de Mesa para N=4 (somatrio dos 4 primeiros nmeros inteiros)

8.3 Quando no se deve empregar recurso


Algoritmos recursivos so particularmente apropriados quando o problema for definido em termos recursivos. Isto no significa, no entanto, que tais definies recursivas garantam ser um algoritmo recursivo a melhor maneira de se resolver o problema. Como exemplo podemos citar o mesmo exemplo do somatrio, para o qual no eficiente usar a recurso e sim a iterao (comandos explcitos de repetio, como: para faa, euquanto faa...), sendo a melhor soluo para o problema. De fato, a apresentao da tcnica atravs de exemplos inadequados tem sido a principal causa da grande apreenso e antipatia criadas contra o uso da recurso nas atividades de programao, bem como pela associao direta entre recurso e ineficincia. Por exemplo, o programa seguinte (Fibonacci), claramente deveria ser resolvido de maneira iterativa. Porm, apenas para fins didticos, posto que ele facilita explicar um tipo especfico de recurso, sua soluo apresentada de maneira recursiva. Para melhor entendimento, ser apresentado o exemplo da seqncia de Fibonacci1: n-simo termo da srie Valor do n-simo termo da srie 1 1 2 1 3 2 4 3 5 5 6 8 7 8 9 10 11 13 21 34 55 89

O processo recursivo, nesse caso, baseado na recorrncia vlida para essa seqncia: todo termo igual soma dos dois termos anteriores. 1, se N = 1 ou N = 2 temos 2 solues triviais Fibonacci(N 1)+Fibonacci(N 2), se N > 2

Fibonacci(N) =

Leonardo Fibonacci (que significa filho de Bonaccio) tambm conhecido por Leonardo Pisano ou Leonardo de Pisa, foi um matemtico italiano nascido em 1180 e falecido em 1250 que ficou conhecido pelo seu livro "Liber Abaci" escrito em 1202 e pela sucesso de nmeros que dele herdou o nome: seqncia de Fibonacci, na qual cada termo resulta da adio dos dois que o antecedem (Un = Un-1 + Un-2) originando assim os nmeros 0; 1; 1; 2; 3; 5; 8; 13; 21 e por a em diante. Os nmeros desta srie tm muitas propriedades e aplicaes interessantes, por exemplo na botnica, no desenvolvimento de plantas(arranjo das folhas), e na gentica, na produo de coelhos.

73

Exemplo de pseudocdigo que calcula o valor do n-simo termo da srie de Fibonacci:


Algoritmo RecursivoFibonacci Variveis n : Inteiro Sub-rotina fibonacci( _n : Inteiro ) : Inteiro Inicio Se (_n = 1) .OU. (_n = 2) Ento Retorne 1 Seno Retorne (fibonacci(_n-1) + fibonacci(_n 2)) Fim_se Fim Inicio Leia(n); Escreva("A Fibonacci "+ fibonacci (n)) Fim.

Como se nota, uma chamada da sub-rotina fibonacci(n) ativa recursivamente esta funo. Observese que cada chamado com n > 1 leva a 2 outras chamadas, isto , o nmero total de chamadas cresce exponencialmente (vide figura abaixo). 1 2 3

10

11 12

13

14

15
Figura 21 - Esquema das chamadas da funo para calcular o valor do 5 termo da srie

De acordo com a ilustrao acima, o clculo do 5 termo da srie, levando em considerao o crescimento exponencial do nmero de chamadas, nos retorna a soluo aps 15 chamadas da funo recursiva. Isso faz com que o programa perca muito em velocidade, sendo assim um programa lento (vide abaixo).

74

Fib(5) Fib(4) Fib(3) Fib(2) 1 2 + Fib(1) 1 3 + 5 + Fib(3) 2 +

Fib(2) 1

Fib(2) 1

Fib(1) 1

Figura 22 - Teste de Mesa para N=5 (calcular o 5 elemento da srie)

Nota-se que, a rvore cresce, de acordo com as chamadas da funo at encontrar uma soluo trivial. Aps encontr-la, as funes retornam os valores obtidos para a funo anterior, at se obter a soluo final (no caso, Fib(5) = 5, ou seja, Fib(4) + Fib(3) 3 + 2 = 5). Felizmente, entretanto, os nmeros de Fibonacci podem ser calculados por um esquema iterativo, que evita o clculo repetido dos mesmos valores, atravs do uso de variveis auxiliares.
Algoritmo IterativoFibonacci Variveis Cont, Post, Ant, Aux, n : Inteiro Inicio cont1 post1 ant0 Leia(n) Enquanto (cont < n) Faa aux post; post post + ant ant aux cont cont + 1 Fim_Enquanto Fim.

Assim, conclui-se que deve ser evitado o uso de recurso sempre que for conhecida uma soluo bvia, que utilize a tcnica de iterao. Entretanto, isto no dever levar a uma rejeio incondicional do uso da tcnica de recurso. Vale lembrar que todo programa recursivo pode ser transformado em outro equivalente, puramente iterativo.

8.4 Vantagens X Desvantagens de um programa recursivo em relao a um programa iterativo


Um programa recursivo mais elegante e menor que a sua verso iterativa, alm de exibir com maior clareza o processo utilizado, desde que o problema ou os dados sejam naturalmente definidos atravs de recorrncia. Por outro lado, um programa recursivo exige mais espao de memria e , na grande maioria dos casos, mais lento do que a verso iterativa.

75

8.5 Mais dois exemplos de programas recursivos 8.5.1 Exemplo 1


Clculo do fatorial de um nmero N. De acordo com a seguinte regra: 1, se N = 0 Fatorial(N) = Fatorial(N 1) * N, caso contrrio

Algoritmo RecursivoFatorial Variveis n : Inteiro Sub-rotina fatorial( _n : Inteiro ) : Inteiro Inicio Se (_n = 0) Ento Retorne 1 Seno Retorne (_n * fatorial(_n 1)) Fim_se Fim Inicio Leia(n) Escreva("A Fatorial "+ fatorial (n)) Fim.

8.5.2 Exemplo 2
Busca Seqencial em um Vetor.
Algoritmo RecursivoBuscaSequencial Variveis lista : VETOR[1:5] de Inteiro ok : Inteiro Sub-rotina busca(ref Vet:VETOR[1:5] de Inteiro; Achou : Logico) inicio /*1*/ K K + 1 /*2*/ Achou .F. /*3*/ Se (X = Vet[i]) Ento /*4*/ Achou .V. Seno /*5*/ Se ((X > Vet[i]) E (i <= N)) Ento /*6*/ busca(Vet, i + 1, N, X, K, Achou) Fim_se Fim_se /*7*/ Escreva ("Fim de chamada: " + K) /*8*/ Escreva ("Sada: " + Achou) Fim Inicio Ok .F. lista[1] 15 lista[2] 17 lista[3] 20 lista[4] 48 lista[5] 53 busca(lista,1,5,20,0,Ok) i, N, X, K: Inteiro, ref

76

Escreva ("Ok: " + Ok) Fim.

A sada do programa ser recebida por passagem do parmetro Achou. O vetor foi definido no programa principal com os seguintes valores: 15 Vetor[1] 17 Vetor[2] 20 Vetor[3] 48 Vetor[4] 53 Vetor[5]

A sub-rotina Busca serve para verificar a ocorrncia de um nmero X em Vetor. A sada diz se X pertence ou no ao Vetor. Na sub-rotina Busca foi declarada o parmetro Vet, que o Vetor, o i, que a posio incio do Vetor, o N, que a posio fim do Vetor, o X, que o valor a ser procurado, o K, que um contador e o Achou, que a resposta da sub-rotina. A idia utilizada na sub-rotina Busca a seguinte: verifique se X o primeiro da lista. Se for, retorne VERDADE; caso contrrio verifique se X o primeiro da sublista que comea na posio 2. Continue reduzindo o tamanho da sublista at encontrar X ou terminar a lista. Colocamos numerao nos comandos da sub-rotina para facilitar a referncia a esses comandos no processo de simulao. Simulao do comando de chamada da sub-rotina busca(lista, 1, 5, 20, 0, Ok) , valores atribudos aos parmetros: 15 list[1] 17 List[2] 20 list [3] 48 list[4] 53 list[5] 1 i 5 N 20 X 0 K .F. Achou

77

Comando 1 2 3

Vet

Execuo K=1 Achou = FALSO Teste X = Vet[i] 20 = 15 FALSO prximo comando: 5 Teste (X > Vet[i]) E (i <= N) (20 > 15) e (1 <= 5) VERDADE prximo comando: 6 busca(Vet, 2, 5, 20, 1, Achou) valores atribudos aos parmetros: 1 2 3 4 5 i N 15 17 20 48 53 2 5

X 20

K 1

Achou FALSO

Comando 1 2 3

Execuo K=2 Achou = FALSE Teste X = Vet[i] 20 = 17 FALSE prximo comando: 5 Teste (X > Vet[i]) && (i <= N) (20 > 17) e (1 <= 5) VERDADE prximo comando: 6 busca(Vet, 3, 5, 20, 2, Achou) valores atribudos aos parmetros: 1 2 3 4 5 i N Vet 15 17 20 48 53 3 5

X 20

K 2

Achou FALSO

Comando 1 2 3

4 5

Execuo K=3 Achou = FALSO Teste X = Vet[i] 20 = 20 VERDADE prximo comando: 4 Achou = VERDADE Sada Fim de chamada: 3 Sada: VERDADE

Sada

Fim de chamada: 2 Sada: VERDADE

Sada

Fim de chamada: 1 Sada: VERDADE

78

Na ilustrao feita anteriormente, cada bloco representa uma chamada da sub-rotina Busca. O bloco externo representa a primeira chamada; o bloco intermedirio, a segunda chamada e o bloco mais interno, a terceira e ltima chamada. Os parmetros que tm passagem por valor (i, N, X e K) exigem uma cpia na memria durante a execuo da sub-rotina. Isto significa que, ao ser executada a terceira chamada de Busca, existem na memria trs variveis com identificador i, trs variveis com identificador N, trs com X e trs com K, cada uma local a uma chamada da sub-rotina. Apenas as estruturas Vet e Achou so globais e esto associadas s variveis lista e Ok do programa principal. Outras aplicaes tradicionais de recursividade podem ser encontradas em: Caminhamento em rvores Binrias, Insero e Busca de elementos em rvores Binrias de Busca, Quicksort, Mergesort.

79

9. rvores
9.1 Introduo
Da mesma forma que as listas lineares, rvores so estruturas de dados que caracterizam uma relao de dados que a compem. No caso de rvores, a relao existente entre os dados (denominados ns ou nodos) uma relao de hierarquia ou de composio, onde um conjunto de dados hierarquicamente subordinado a outro de dados. Formalmente, uma rvore um conjunto finito T de um n ou mais ns, tais que: a) existe um n denominado raiz da rvore; b) os demais ns forma m>= 0 conjuntos disjuntos S1, S2, ... , Sm, onde cada um destes conjuntos uma rvore. As rvores Si (1<= i <= n) recebem a denominao de sub-rvores. Esquematicamente, uma rvore pode ser representada da seguinte maneira:

Figura 23 - Esquema rvore

Os crculos representam os ns da rvore, cuja raiz o n A.

9.2 Terminologia
Pela definio de rvore, cada n da rvore a raiz de uma sub-rvore. O n principal de uma arvore chama-se raiz. O nmero de sub-rvores de um n determina o grau daquele n. Um n de grau igual a zero e denominado folha ou n terminal O nvel do n definido da seguinte forma: a raiz da rvore tem nvel 0, enquanto o nvel dos demais ns igual ao nmero de linhas que o liga raiz. A altura de uma rvore considera-se o maior nvel encontrado, ou seja, na arvore da figura abaixo tem altura 4. Denomina-se floresta um conjunto de zero ou mais rvores disjuntas. Assim, se eliminarmos o n raiz de uma rvore, o que dela restar forma uma floresta. Inversamente se unirmos as razes das rvores que formam uma floresta com um n adicional, formamos uma rvore.

80

NVEL 0

PAI

RAIZ

A
NVEL 1 FILHO

B
FOLHA NVEL 2

FILHO

RAIZ DA SUBRVORE ALTURA

E
FOLHA

NVEL 3

G
FOLHA

H
FOLHA

I
FOLHA SUBRVORE

Figura 24 - Definies de rvore

N A B C D E F G H I

Grau 2 0 3 2 0 1 0 0 0

Nvel 0 1 1 2 2 2 3 3 3

Obs. Raiz da rvore

N terminal ou Folha N terminal ou Folha N terminal ou Folha N terminal ou Folha

Figura 25 - Detalhamento de grau e nvel

A raiz de uma rvore chamada de pai das razes das duas sub-rvores. As razes das sub-rvores de um n so chamadas de irmos que, por sua vez, so filhos de seu n pai. N A B C D E F G H I Pai B,C D, E, F G, H I Filho A A C C C D D F Irmo C B E,F D,F D,E H G -

Figura 26 - Detalhamento de filho e irmo

Quando a ordem da matriz significativa diz-se que ordenada. Neste caso, pode-se falar em primeira sub-rvore , segunda sub-rvore etc. Desta forma, as duas rvores abaixo so diferentes.

81

<>
B C C B
Figura 27 - rvore Ordenada

Ordenada

Quando, entretanto, a ordem das sub-rvores no relevante, dizemos que a rvore orientada, uma vez que apenas a orientao dos ns importante. Neste caso, as duas rvores da figura abaixo so iguais.

=
B C C B
Figura 28 - rvore Orientada

Orientada

9.3 Representaes Bsicas para rvores 9.3.1 Diagrama de Incluso


A H B D G F I C E

Figura 29 Diagrama Incluso

9.3.2 Representao Hierrquica


A

Figura 30 Representao Hierrquica

82

9.3.3 Diagrama de Barras

A B C

D G H E F I

Figura 31 Diagrama de Barras

9.3.4 Parntesis Aninhados

(A (B) (C (D (G) (H)) (E) (F (I))))


9.3.5 Representao Matricial
ndice 1 2 3 4 5 6 7 8 9 Informao A B C D E F G H I 1a Sub-rvore 2 0 4 7 0 9 0 0 0 2a Sub-rvore 3 0 5 8 0 0 0 0 0 3a Sub-rvore 0 0 6 0 0 0 0 0 0

No caso da representao matricial, o n raiz da rvore ocupa a primeira linha da matriz. Quando alguma das sub-rvores de um n raiz se apresentar vazia, a coluna do ndice correspondente desta subrvore vale 0. Um n folha apresenta todas as colunas de suas sub-rvores iguais a 0.

9.4 rvore Binria


rvores binrias so estruturas do tipo rvore, onde o grau de cada n menor ou igual a dois. No caso de rvores binrias, distinguem-se as sub-rvores de um n entre rvores da esquerda e sub-rvores da direita. Assim, se o grau de um n for igual a 1, deve ser especificado se a sua sub-rvore a da esquerda ou a da direita. Uma rvore binria tambm pode ser vazia, isto , no possuir nenhum n.

83

Figura 32 rvore Binria

9.4.1 Tipos de rvores Binrias


Uma rvore estritamente binria aquela em que cada n possui exatamente 0 ou 2 ns. O item a) da figura abaixo apresenta uma rvore estritamente binria. Uma rvore binria completa aquela que apresenta a seguinte propriedade: se v um n tal que alguma sub-rvore de v vazia, ento v se localiza no penltimo ou ltimo nvel da rvore. O item b) da figura abaixo apresenta uma rvore binria completa. Uma rvore binria cheia aquela em que, se v apresenta uma de suas sub-rvores vazia ento v se encontra obrigatoriamente no ltimo nvel da rvore. Pode-se afirmar que uma rvore binria cheia tambm completa e estritamente binria. O item c) da figura abaixo apresenta uma rvore binria cheia.

a)

b)
Figura 33 Tipos de rvores

c)

rvores binrias ziguezague ou degeneradas so aquelas que apresentam sempre a altura h mxima possvel dados os n ns da rvore. A figura abaixo apresenta diferentes rvores ziguezague.

84

a)

b)

c)

d)

Figura 34 rvores degeneradas

A altura h mnima para uma rvore binria de n ns conseguida sempre que esta rvore binria for do tipo completa. possvel deduzir a altura mnima para uma rvore de n ns atravs da seguinte frmula usando logaritmo na base 2:

h min = 1 + |log2 n |
onde n = nmero de ns da rvore. Ex: para uma rvore binria de 15 ns:

h min = 1 + | log2 15| h min = 1 + |3.9| h min = 1 + 3 h min = 4


Esta deduo pode ser comprovada ao se analisar a rvore do item c) da figura acima, que por ser do tipo cheia apresenta a altura mnima (igual a 4) dados os seus 15 ns.

9.4.2 Caminhamento em rvore Binria


Uma das mais importantes operaes que pode ser aplicada em uma rvore binria o caminhamento, isto , a habilidade de se mover atravs de todos os seus ns. Cada caminhamento impe uma ordenao sobre os ns da rvore, isto , a ordem na qual eles so acessados. Dos diversos tipos de caminhamentos definidos, os trs principais (central, pr-fixado e psfixado) so apresentados abaixo. O princpio bsico para a execuo destes caminhamentos decidir se o n raiz vai ser visitado antes de se caminhar para as suas subrvores, durante este caminhamento, ou depois que todas as subrvores terem sido visitado. Os 3 tipos de caminhamento so resumidos a seguir: a) Caminhamento Pr-Ordem ou Pr-Fixado: 1) Visite a Raiz; 2) Visite a Subrvore Esquerda; 3) Visite a Subrvore Direita; b) Caminhamento Central: 1) Visite a Subrvore Esquerda; 2) Visite a Raiz; 3) Visite a Subrvore Direita; c) Caminhamento Ps-Ordem ou Ps-Fixado:

85

1) Visite a Subrvore Esquerda; 2) Visite a Subrvore Direita; 3) Visite a Raiz; Ex:

Figura 35 Caminhamentos em rvores

A figura abaixo mostra a seqncia em que o caminhamento central (Esquerda, Raiz, Direita) executado em uma rvore binria.

ERD
A

ERD
B C

ERD

ERD
D

4 3 2 1
Figura 36 Caminhamento Central

O ponto de partida a raiz da rvore 1 (n A). Na rvore 1 devem-se ser visitadas a sua sub-rvore da esquerda, a sua raiz e depois a sua sub-rvore da direita. A sub-rvore esquerda da rvore 1 a rvore 2, cuja raiz o n B. Na sub-rvore 2 devem ser visitadas a sua sub-rvore da esquerda, a sua raiz e depois a sua subrvore da direita. A sub-rvore esquerda da rvore 2 a rvore 3, cuja raiz o n D. Na sub-rvore 3 devem ser visitadas a sua sub-rvore da esquerda, a sua raiz e depois a sua subrvore da direita. Uma vez que no existe sub-rvore esquerda de D, o prximo n a se visitar a raiz (n D) da rvore 3. Uma vez que tambm no existe sub-rvore direita de D, o caminhamento central na rvore 3 est terminado.

86

Encerrado o caminhamento na rvore 3, retoma-se o caminhamento na rvore 2, que neste instante teve apenas a sua sub-rvore da esquerda visitada, restando ainda visitar-se a sua raiz (n B) e sub-rvore da direita. Uma vez que no existe sub-rvore direita de B, o caminhamento central na rvore 2 est terminado. Encerrado o caminhamento na rvore 2, retoma-se o caminhamento na rvore 1, que neste instante teve apenas a sua sub-rvore da esquerda visitada, restando ainda visitar-se a sua raiz (n A) e sub-rvore da direita. A sub-rvore direita da rvore 1 a rvore 4, cuja raiz o n C. Na sub-rvore 4 devem ser visitadas a sua sub-rvore da esquerda, a sua raiz e depois a sua subrvore da direita. Uma vez que no existe sub-rvore esquerda de C, o prximo n a se visitar a raiz (n C) da rvore 4. Uma vez que tambm no existe sub-rvore direita de C, o caminhamento central na rvore 4 est terminado. Para o exemplo, encerrado o caminhamento central na rvore 4, encerra-se tambm o caminhamento central na rvore 1, uma vez que tanto as sub-rvores esquerda e direita desta rvore quanto sua raiz j foram visitadas.

9.4.3 Inserindo dados em uma rvore Binria


O processo de colocao um elemento do conjunto de dados na rvore obedece a seguinte regra: se a rvore estiver vazia, o elemento colocado na raiz da rvore; caso contrrio, se o elemento for menor ou igual ao elemento da raiz, ele posicionado esquerda deste. Se o elemento for maior do que o da raiz, ele posicionado direita da mesma.

Esta sub-rotina, caso aplicado ao conjunto de dados apresentado a seguir:

42-51-19-37-42-86-71-10-75-22-31-42
Resulta na rvore binria colocada abaixo:

Figura 37 Insero dados em rvores

O caminhamento central na rvore devolve os elementos em ordem crescente.

9.4.4 Aplicaes de rvores Binrias


A estrutura de rvore utilizada em casos onde os dados ou objetos a serem representados possuem relaes hierrquicas entre si. Desenvolvimento de sistemas com tabelas, simulao de calculadoras e resoluo de expresses matemticas, mecanismos de busca.

87

Outra aplicao de rvore binria a ordenao e pesquisa de conjuntos de dados. Estas rvores so denominadas rvores binrias de busca ou de pesquisa/ordenao (ABPO).

9.4.4.1 Resoluo de Expresses Matemticas


A estrutura de rvore binria pode ser utilizada em casos onde os dados ou objetos a serem representados possuem uma relao de hierarquia entre si, como por exemplo, no caso da expresso matemtica abaixo:

a * b + c / (d + e)
onde a relao hierrquica aparece na medida em que alguns operadores da expresso tm maior precedncia sobre outros, tornando possvel a sua representao atravs da seguinte rvore binria:

Figura 38 Expresses Matemticas em rvores

A representao feita de modo que a prioridade das operaes fique implcita: o operador de menor prioridade da expresso fica na raiz da rvore. A sub-expresso que forma o operando da esquerda do operador d origem a sub-rvore esquerda da raiz. Analogamente, o operando da direita d origem sub-rvore da direita. O caminhamento central sobre a rvore devolve a expresso original, enquanto que os caminhamentos pr-ordem e ps-ordem devolvem a expresso na forma pr-fixada e ps-fixada, respectivamente.

9.5 Alocao
semelhana de que acontece com listas, s rvores podem ser alocadas na memria de um computador por contigidade ou por encadeamento. No caso de rvores, h ainda a considerar uma alocao mista.

9.5.1 Alocao com Contigidade


Nesta modalidade, os ns da rvore so representados seqencialmente na memria, de acordo com uma determinada ordem convencionada em que eles aparecem na rvore. A alocao seqencial no constitui uma maneira conveniente para representar rvores, na maioria dos casos. Isto se deve s dificuldades que ela oferece para manipulaes da estrutura (inseres, remoes e localizao de um n particular).

88

A
1 2 B 3 C A

Vetor C 4 D 5 E 6 F 7 G

G
Figura 39 Alocao de rvores

Dado um vetor de chaves C1, C2,... Cn consideramos este vetor como sendo a representao de uma rvore binria, usando a seguinte representao dos ndices das chaves. C1 raiz da rvore C2i = sub-rvore da esquerda de Ci C2i+1 = sub-rvore da direita de Ci

para i = 1, n (diviso inteira) 2 Esta forma de alocao til, entretanto, quando os ns da rvore devem ser processados na mesma ordem em que aparecem na alocao seqencial. o caso, por exemplo, de armazenamento permanente de rvores representadas por encadeamento. Neste caso, a representao encadeada transformada em representao seqencial para fins de armazenamento permanente. Quando for necessrio efetuar manipulaes sobre a rvore, ela novamente transformada para a forma encadeada e, ento, manipulada.

9.5.2 Alocao com Encadeamento


A alocao por encadeamento oferece, de um modo geral, uma alternativa mais adequada para representao de rvores, permitindo, com igual facilidade, manipulaes das rvores, bem como diversas ordens de acesso aos ns. Na alocao encadeada, cada n um dado que pode ser alocada dinamicamente e possui espao para representar tanto a informao do n como as referncias das sub-rvores daquele n. O problema principal deste esquema devido ao fato de cada n poder ter um nmero diferente de sub-rvores (grau). A soluo imediata fazer com que o tipo de dado dos ns tenha tantas referncias quanto o nmero mximo de sub-rvores que um n possa ter. Com esta organizao h, geralmente, uma grande quantidade de referncias no usadas naqueles ns de grau menor do que o mximo previsto. A soluo alternativa mais econmica para este caso e transformar a rvore a ser representada em rvore binria, onde o grau mximo de um n qualquer 2. Cada n de uma rvore binria ter a funo de armazenar os endereos dos filhos de cada n raiz de uma sub-rvore. Estes filhos, enquanto razes de outras sub-rvores, tambm armazenaro o endereo de seus filhos, e assim por diante. Nas folhas da rvore, o ns no possuem mais filhos, por isso seus ponteiros vo apontar para nulo, indicando o fim daquela sub-rvore. Esquematicamente:

89

RAIZ

ESQ

DADO

DIR

A
ESQ DADO DIR ESQ DADO DIR

B
ESQ DADO DIR ESQ DADO DIR

C
ESQ DADO DIR

E
ESQ DADO DIR

G
Figura 40 Alocao por encadeamento

A estrutura necessria para se representar uma rvore binria seria:


TipoDado : Inteiro No : Registro Esquerda : No Dado : TipoDado Direita : No Fim_registro Variveis raiz: No

onde o campo dado tem a funo de guardar o elemento a ser armazenado no n da rvore; o campo esquerda guarda o endereo do filho esquerda do n e o campo direita guarda o endereo do filho direita do n. Em uma rvore binria de busca existem basicamente 4 operaes que podem ser efetuadas: caminhamento (pr-fixado, central e ps-fixado); inserir um novo elemento na rvore; pesquisar um elemento na rvore remover um elemento da rvore

9.6 Implementao rvore Binria


No exemplo do fatorial recursivo, a implementao iterativa tende a ser ligeiramente mais rpida na prtica do que a implementao recursiva, uma vez que uma implementao recursiva precisa registrar o estado atual do processamento de maneira que ela possa continuar de onde parou aps a concluso de cada nova excecuo subordinada do procedimento recursivo. Esta ao consome tempo e memria. (Note que a implementao de uma funo fatorial para nmeros naturais pequenos mais rpida quando se usa uma tabela de busca.) Existem outros tipos de problemas cujas solues so inerentemente recursivas, j que elas precisam manter registros de estados anteriores. Um exemplo o percurso de uma rvore; outros exemplos incluem a funo de Ackermann e algoritmos de diviso e conquista tais como o Quicksort. Todos estes algoritmos podem ser implementados iterativamente com a ajuda de uma pilha, mas o uso de uma pilha, de certa forma, anula as vantagens das solues iterativas.

90

Outra possvel motivao para se escolher um algoritmo iterativo ao invs de um algoritmo recursivo que nas linguagens de programao modernas o espao disponvel para o fluxo de controle geralmente bem menor que o espao disponvel no heap, e algoritmos recursivos tendem a necessitar de mais espao na pilha do que algoritmos iterativos.

9.6.1 Implementao Recursiva de rvores Binrias de Busca


Algoritmo Arvore_Binaria_Encadeada Tipo TipoDado : Inteiro No : Registro Esquerda : No Dado : TipoDado Direita : No Fim_registro Variveis raiz opcao val

: No : Inteiro : TipoDado

Inicio raiz nulo //Inicializa a raiz da rvore opcao -1 // Menu para chamada das operaes de uma rvore Enquanto opcao <> 7 faa Escreva( 1 Inserir 2 Remover 3 Pesquisar 4 CaminhoCentral 5 CaminhoPre 6 CaminhoPos 7 Sair) Leia(opcao) Se opcao = 1 ento Escreva(Qual o valor a inserir ? ) Leia val inserir(raiz, val) Seno Se opcao = 2 ento Escreva(Qual o valor a inserir ? ) Leia val remover(raiz, val) Seno Se opcao = 3 ento Escreva(Qual o valor a pesquisar ? ) Leia val Se pesquisar(raiz, val) <> Nulo Ento Escreva(No Encontrado!) Fim_se Seno Se opcao = 4 ento caminhoCentral(raiz) Seno Se opcao = 5 ento caminhoPreOrdem(raiz) Seno Se opcao = 6 ento caminhoPosOrdem(raiz) Fim_se //6 Fim_se //5 Fim_se //4 Fim_se // 3 Fim_se //2

91

Fim_se //1 Fim_enquanto Fim. //Sub-rotina inserir tem o argumento _valor passado por valor com os dados de um novo n. O argumento _raiz passado por referncia que o incio da rvore. Sub-rotina inserir(ref _raiz : No; _valor : TipoDado) Variveis novo : No Inicio Se _raiz = nulo ento aloca (novo) novo.esquerda nulo novo.dado _valor novo.direita nulo _raiz novo Seno Se valor < _raiz.dado Ento inserir (_raiz. esquerda, _valor)) Seno Se valor > _raiz.dado Ento inserir(_raiz. direita, _valor)) Seno Escreva (Valor j existe na rvore!) Fim_se Fim_se Fim_se Fim //Sub-rotina sucessor tem os argumento _raiz passado por valor e _suc passado por referncia. O argumento _raiz.dado ter o seu valor substitudo pelo sucessor e _suc ser removido.. Sub-rotina sucessor (_raiz : No; ref _suc : No) Variveis temp : No Inicio Se _suc.esquerda <> nulo ento sucessor (_raiz, _suc.esquerda) Seno _raiz.dado _suc.dado temp _suc _suc _suc.direita desaloca(temp) Fim_se Fim //Sub-rotina remover tem o argumento _valor passado por valor com os dados de n a ser removido. O argumento _raiz passado por referncia o incio da rvore. Sub-rotina remover(ref _raiz : No; _valor : TipoDado) Variveis temp : No Inicio Se _raiz <> nulo ento Se _valor < _raiz.dado Ento remover (_raiz. esquerda, _valor)) Seno Se _valor > _raiz.dado Ento remover(_raiz. direita, _valor)) Seno

92

Se _raiz.direita = nulo ento temp _raiz; _raiz _raiz.esquerda desaloca(temp) Seno Se _raiz.esquerda = nulo ento temp _raiz; _raiz _raiz.direita desaloca(temp) Seno sucessor(_raiz, _raiz.direita) Fim_se Fim_se Fim_se Fim_se Seno Escreva (Valor no existe na rvore!) Fim_se Fim //Sub-rotina pesquisa tem o argumento _valor passado por valor com os dados de um novo n. O argumento _raiz passado por valor o incio da rvore. A sub-rotina retorna o n se encontrar o valor na rvore caso contrrio retorna nulo. Sub-rotina pesquisar (_raiz : No; _valor : TipoDado) : No Inicio Se _raiz = nulo ento Retorna (nulo) Seno Se valor = _raiz.dado Ento Retorna (_raiz) Seno Se valor < _raiz.dado Ento Retorna (Pesquisar(_raiz. esquerda, _valor)) Seno Se valor > _raiz.dado Ento Retorna (Pesquisar(_raiz. direita, _valor)) Fim_se Fim_se Fim_se Fim_se Fim

//Sub-rotina caminhoCentral tem o argumento _raiz passado por valor que o incio da rvore. Sub-rotina caminhoCentral (_raiz : No) Inicio Se _raiz <> nulo ento caminhoCentral (_raiz.esquerda) Escreva(_raiz.dado); caminhoCentral (_raiz.direita) Fim_se Fim //Sub-rotina caminhoPreOrdem tem o argumento _raiz passado por valor que o incio da rvore. Sub-rotina caminhoPreOrdem (_raiz : No)

93

Inicio Se _raiz <> nulo ento Escreva(_raiz.dado); caminhoPreOrdem (_raiz.esquerda) caminhoPreOrdem (_raiz.direita) Fim_se Fim //Sub-rotina caminhoPosOrdem tem o argumento _raiz passado por valor que o incio da rvore. Sub-rotina caminhoPosOrdem (_raiz : No) Inicio Se _raiz <> nulo ento caminhoPosOrdem (_raiz.esquerda) caminhoPosOrdem (_raiz.direita) Escreva(_raiz.dado); Fim_se Fim

9.6.2 Implementao Iterativa de rvores Binrias de Busca


Algoritmo Arvore_Binaria_Encadeada_Iterativa Tipo TipoDado : Inteiro NoPilha : Registro Dado : No Proximo : NoPilha Vez : Inteiro Fim_registro No : Registro Esquerda : No Dado : TipoDado Direita : No Fim_registro Variveis raiz opcao val

: No : Inteiro : TipoDado

Inicio raiz nulo //Inicializa a raiz da rvore opcao -1 // Menu para chamada das operaes de uma rvore Enquanto opcao <> 7 faa Escreva( 1 Inserir 2 Remover 3 Pesquisar 4 CaminhoCentral 5 CaminhoPre 6 CaminhoPos 7 Sair) Leia(opcao) Se opcao = 1 ento Escreva(Qual o valor a inserir ? ) Leia val inserir(raiz, val) Seno Se opcao = 2 ento Escreva(Qual o valor a inserir ? ) Leia val remover(raiz, val) Seno Se opcao = 3 ento

94

Escreva(Qual o valor a pesquisar ? ) Leia val Se pesquisar(raiz, val) <> Nulo Ento Escreva(No Encontrado!) Fim_se Seno Se opcao = 4 ento caminhoCentral(raiz) Seno Se opcao = 5 ento caminhoPreOrdem(raiz) Seno Se opcao = 6 ento caminhoPosOrdem(raiz) Fim_se //6 Fim_se //5 Fim_se //4 Fim_se // 3 Fim_se //2 Fim_se //1 Fim_enquanto Fim. //Sub-rotina inicializaPilha tem o argumento _topo passado por referncia. Sub-rotina inicializaPilha(ref _topo : NoPilha) Inicio _topo nulo Fim //Sub-rotina empilhar tem o argumento _topo passado por referncia que o topo da pilha. O argumento _valor passado por valor com os dados de um No da rvore a ser empilhada Sub-rotina empilhar(ref _topo : NoPilha; _valor : No) Variveis novo : No Inicio Aloca(novo) // obtm espao para um novo no novo.dado _valor // armazena valor no novo no // garante que o n ter o prximo a partir do topo anterior novo.proximo _topo _topo novo // atribui o novo topo Escreva (Elemento empilhado com sucesso) Fim //Sub-rotina empilhar tem o argumento _topo passado por referncia que o topo da pilha. O argumento _valor passado por valor com os dados de um No da rvore a ser empilhada. O argumento _vez passado por referncia indica a vez do n no caminhamento Sub-rotina empilhar(ref _topo : NoPilha; _valor : No; ref _vez: Inteiro) Variveis novo : No Inicio Aloca(novo) // obtm espao para um novo no novo.dado _valor // armazena valor no novo no novo.vez _vez // armazena a vez do n no caminhamento // garante que o n ter o prximo a partir do topo anterior novo.proximo _topo _topo novo // atribui o novo topo Escreva (Elemento empilhado com sucesso) Fim

95

//Sub-rotina desempilhar tem o argumento _topo passado por referncia que o topo da pilha. Sub-rotina desempilhar(ref _topo : NoPilha) Variveis temp : No Inicio Se _topo <> nulo ento temp _topo // // guarda ponteiro do elemento a ser excludo // garante que o n ter o prximo a partir do incio anterior _topo _topo.proximo desaloca(temp) // desaloca temp devolvendo o espao ao S.O. Escreva (Elemento desempilhado com sucesso) Seno Escreva (Pilha Vazia) Fim_se Fim //Sub-rotina acessarTopo tem o argumento _topo passado por valor. argumento _topo indica onde comea a pilha. Sub-rotina acessarTopo (_topo: No) : No Inicio Se _topo <> nulo ento Retorna _topo.dado Seno Retorna nulo Fim_se Fim O

//Sub-rotina acessarTopo tem o argumento _topo passado por valor. O argumento _topo indica onde comea a pilha, o argumento _vez passado por referncia e indica a vez do n no caminhamento. Sub-rotina acessarTopo (_topo: No; ref _vez : Inteiro) : No Inicio Se _topo <> nulo ento _vez _topo.vez Retorna _topo.dado Seno Retorna nulo Fim_se Fim //Sub-rotina inserir tem o argumento _valor passado por valor com os dados de um novo n. O argumento _raiz passado por referncia que o incio da rvore. Sub-rotina inserir(ref _raiz : No; _valor : TipoDado) Variveis novo, atual, anterior : No Inicio aloca (novo) novo.esquerda nulo novo.dado _valor novo.direita nulo Se _raiz = nulo ento _raiz novo Seno atual _raiz anterior nulo Enquanto (atual <> nulo) faa anterior atual Se (_valor < atual.dado) Ento

96

atual atual.esquerda Seno atual atual.direita Fim_se Fim Enquanto Se (_valor < anterior.dado) Ento anterior.esquerda novo Seno Se (_valor > anterior.dado) Ento anterior.direita novo Seno Se (_raiz.dado = _valor ) Ento Escreva (Valor j existe na rvore!) Seno Escreva (Valor j existe na rvore!) Fim_se Fim_se Fim_se Fim_se Fim //Sub-rotina pesquisa tem o argumento _valor passado por valor com os dados de um novo n. O argumento _raiz passado por valor o incio da rvore. A sub-rotina retorna o n se encontrar o valor na rvore caso contrrio retorna nulo. Sub-rotina pesquisar (_raiz : No; _valor : TipoDado) : No Variveis achei : No Inicio achei nulo Se _raiz = nulo ento Retorna (nulo) Seno atual _raiz Enquanto (atual <> nulo) .E. (achei=nulo) faa Se _valor = atual.dado Ento achei atual Seno Se (_valor < atual.dado) Ento atual atual.esquerda Seno atual atual.direita Fim_se Fim_se Fim Enquanto Retorna (achei) Fim_se Fim //Sub-rotina caminhoCentral tem o argumento _raiz passado por valor que o incio da rvore. Sub-rotina caminhoCentral (_raiz : No) Variveis fim : Lgico topo : NoPilha atual : No Inicio fim .falso. inicializaPilha(topo) atual _raiz Enquanto (fim = .falso.) faa

97

Enquanto (atual <> nulo) faa empilhar(topo,atual) atual atual.esquerda Fim_enquanto atual acessarTopo(topo) desempilhar(topo) Se (atual = nulo) ento fim .verdade. Seno Escreva(_atual.dado) //Utiliza o n atual atual.direita Fim_se Fim_enquanto Fim //Sub-rotina caminhoPreOrdem tem o argumento _raiz passado por valor que o incio da rvore. Sub-rotina caminhoPreOrdem (_raiz : No) Variveis topo : NoPilha atual : No Inicio inicializaPilha(topo) atual _raiz empilhar(topo,atual) Enquanto (topo <> nulo) faa atual acessarTopo(topo) desempilhar(topo) Se atual <> nulo ento Escreva(_atual.dado) //Utiliza o n empilhar(topo, atual.direita) empilhar(topo, atual.esquerda) Fim_se Fim_enquanto Fim //Sub-rotina caminhoPosOrdem tem o argumento _raiz passado por valor que o incio da rvore. Sub-rotina caminhoPosOrdem (_raiz : No) var fim : Lgico topo : NoPilha atual : No vez : inteiro Inicio fim .falso. vez 0 inicializaPilha(topo) atual _raiz Enquanto (fim = .falso.) faa Enquanto (atual <> nulo) faa empilhar(topo,atual,1) //Passa a vez para direita atual atual.esquerda Fim_enquanto atual acessarTopo(topo,vez) //vez passado por referncia desempilhar(topo) Se (atual = nulo) ento fim .verdade. Seno Se (vez = 1) ento empilhar(atual,2) //Passa a vez para a esquerda

98

atual atual.direita Seno Escreva(_atual.dado) //Utiliza o no atual nulo Fim_se Fim_se Fim_enquanto Fim

9.7 rvores B
rvores-B ou B-Tree so rvores balanceadas projetadas para trabalhar com dispositivos de armazenamento secundrio como discos magnticos. Elas visam otimizar as operaes de entrada-sada nos discos. O tempo de acesso a informaes em um disco prejudicado principalmente pelo tempo de posicionamento do brao de leitura. Uma vez que o brao esteja posicionado no local correto, a leitura pode ser feita de forma bastante rpida. Desta forma, devemos minimizar o nmero de acessos ao disco. muito utilizada em banco de dados e em sistemas de arquivos. Diferente das rvores binrias, cada n em uma rvore-B pode ter muitos filhos, isto , o grau de um n pode ser muito grande. Para inserir ou remover dados de um n, a quantidade de descendentes no n no poder ultrapassar sua ordem e nem ser menor que sua ordem dividida por dois (fator de preenchimento). rvores B tm vantagens substanciais em relao a outros tipos de implementaes quanto ao tempo de acesso e pesquisa aos ns. Rudolf Bayer and Edward M. McGreight, em 1972, publicaram o artigo: "Organization and Maintenance of Large Ordered Indexes". Em 1979, o uso de rvores-B j era praticamente o padro adotado em sistemas de arquivos de propsito geral para a manuteno de ndices para bases de dados. Rudolf Bayer, no definiu claramente de onde veio o B das rvores B. Ao que parece, o B vem de balanceamento onde todos os ns folhas da rvore esto em um mesmo nvel. Tambm possvel que o B tenha vindo de seu sobrenome Bayer, ou ainda do nome da empresa onde trabalhava, a Boeing Scientific Research Labs.

9.7.1 Definio
Uma rvore B de ordem "m" uma rvore que atende as seguintes propriedades: 1) 2) 3) 4) 5) Cada n tem no mximo "m" filhos Cada n (exceto a raz e as folhas) tem pelo menos "m/2" filhos A raiz tem pelo menos dois filhos se ela mesma no for uma folha Todas as folhas aparecem no mesmo nvel e carregam informao Um n no-folha com "k" filhos deve ter k-1 chaves.

9.7.2 Estrutura do N
Ns em rvores B, tambm denominado pginas, geralmente so representados por um conjunto de elementos apontando para seus filhos, estes que por sua vez tambm podem ser conhecidos como folhas. Alguns autores consideram a ordem de uma rvore B como sendo a quantidade de registros que a pgina pode suportar. Outros consideram a ordem como a quantidade de campos apontadores. Todo n da rvore tem um nmero mnimo de elementos, que dado pela metade do valor da ordem do n, truncando o nmero caso a rvore seja de ordem mpar, exceto para a raiz da rvore, que pode ter o mnimo de um registro. Por exemplo, os ns de uma rvore de ordem 5, devem ter, no mnimo 5 / 2 = 2,5 registros, ou seja, dois registros. A quantidade de filhos que um n pode ter sempre a quantidade de registros do n mais 1 (V+1). Por exemplo, se um n tem 4 registros, este n ter obrigatoriamente 5 apontamentos para os ns filhos. A estrutura necessria para se representar uma rvore B:
Constantes NUMERO_CHAVES = 3

99

NUMERO_FILHOS = 4 TipoDado : Inteiro No : Registro numero_chaves : Inteiro chaves : VETOR[1:NUMERO_CHAVES] de TipoDado filhos : VETOR[1:NUMERO_FILHOS] de No Fim_registro Variveis raiz: No

onde o vetor chaves tem a funo de guardar o elemento as chaves a serem armazenado no n da rvore; o vetor filhos guarda o endereo dos filhos do n e o campo numero_chaves guarda a quantidade ns filhos do n.

9.8 rvores B+
Uma das maiores deficincias da rvore-B a dificuldade de percorrer as chaves seqencialmente. Uma variao da estrutura bsica da rvore-B a rvore-B+. Estrutura da rvore B+: Todas as chaves so mantidas em folhas; As chaves so repetidas em ns no-folha formando um ndice para localizar registros individuais; As folhas so ligadas atravs de uma lista duplamente encadeada oferecendo um caminho seqencial para percorrer as chaves.

importante esta separao lgica da rvore-B+ em Conjunto de ndices e Conjunto de Seqncia, pois podemos fazer a maioria das incluses e excluses no conjunto de seqncia sem alterar o ndice (rvore-B). Quando houver necessidade de incluso ou excluso do referido ndice, usamos os algoritmos j conhecidos da rvore- B. A insero numa rvore-B+ ocorre praticamente da mesma forma que numa rvore-B, exceto pelo fato de que, quando um n dividido, a chave do meio retida no meio n esquerdo, alm de ser promovida a pai. Quando uma chave eliminada de uma folha, ela pode ser retida nas no-folhas porque ela ainda um separador vlido entre as chaves nos ns abaixo dela. A rvore-B+ mantm o baixo custo das operaes de pesquisa, incluso e excluso e adquire a vantagem de requerer no mximo um acesso para satisfazer a operao da prxima chave. Alm disso, para um processamento seqencial nenhum nodo precisar ser acessado mais de uma vez como acontece no caminhamento em-ordem que precisamos fazer numa rvore -B. Portanto, enquanto a eficincia de localizao do registro seguinte em um rvore-B O(log n), numa rvore-B+ aumentada para O(1). A rvore-B+ ideal para aplicaes que requerem tanto acesso seqencial quanto aleatrio. Por isso e pelas vantagens citadas anteriormente, a rvore -B+ tornou-se bastante popular nos SGBDs comerciais. Muitos Bancos de Dados so construdos usando o mecanismo de rvores B+ como SQLServer e Oracle.

100

10. Clculo de Endereo


10.1 Introduo
O mtodo de clculo de endereo (Hashing) no apenas um mtodo de pesquisa mas tambm um mtodo de organizao(classificao). Os endereos gerados so colocados em uma tabela chamada hashing, disperso ou espalhamento. Um dos maiores problemas encontrados quando se estuda a alocao de estrutura de dados o tempo de resposta da pesquisa de uma chave em um conjunto C de elementos. Em se tratando de tabelas hashing, esse tempo corresponde ao tempo de recuperao de determinado elemento. Quando pensamos em pesquisa de uma chave em uma tabela, na maioria das vezes optamos por base-la na comparao de um argumento dado(K), com todas as chaves da tabela ou usar o conhecimento da natureza dos dados. Observe que nesse caso o tempo de pesquisa depende do nmero de elementos da tabela e do mtodo de pesquisa utilizado. interessante, porm, analisar uma outra alternativa, que baseada no clculo da posio do registro em um tabela atravs do uso de funes aritmticas f(K) que tm com argumento o valor da chave K, o que permite que o tempo de pesquisa seja independente do nmero de registros da tabela. O uso de funes para localizar elementos em uma tabela a partir da converso de chaves em um nmero (o seu endereo) chamado de hashing. Esse nome derivado do verbo em ingls to hash, que significa desmembrar, cortar mido ou ainda desorganizar. Esse nome pouco formal para esse mtodo se deve caracterstica de espalhar os dados de uma coleo em um intervalo, o mais distribudo possvel. Por ser uma funo que gera um valor a partir de uma determinada chave, tambm chamaremos hashing de tcnica de transformao de chaves. Definimos uma funo hashing como sendo um mapeamento H : K -> E
chave

E = H(K)

Figura 41 - Funo hashing

onde K a chave que identifica um elemento em um tabela, E o endereo onde esse elemento est (ou deveria estar) e H a funo finita e no-recursiva que, dado um valor para k retorna um e apenas um valor para E. Observe que o hashing de duas chaves K1 e K2 podem levar ao mesmo endereo E. Nesse momento, est caracterizada uma coliso. A funo de hashing ideal aquela que no permite que ocorram colises. Se no for possvel identificar uma funo hashing ideal, as colises devem ser tratadas. O famoso Paradoxo do Aniversrio um bom exemplo para ilustrar o quanto funes idias so difceis de serem encontradas. Se 23 pessoas ou mais esto presentes em uma sala, existem grandes chances de que duas delas tenham o mesmo dia e o mesmo ms de nascimento. Em outras palavras, se ns selecionarmos uma funo randmica que mapeia 23 chaves numa tabela de tamanho 365 (dias do ano), a probabilidade de que no existam duas chaves mapeadas no mesmo lugar de apenas 0,4927 (nem mesmo a metade). Considerando a dificuldade em se encontrar funes hashing ideais, um algoritmo de hashing completo deve consistir em uma funo hashing e de um tratamento de colises.

101

10.2 Vantagens e Desvantagens


Como vantagens podemos citar: Simplicidade - muito fcil de imaginar um algoritmo para implementar hashing. Escalabilidade - Podemos adequar o tamanho da tabela de hashing ao n esperado em nossa aplicao. Eficincia para n grandes - Para trabalharmos com problemas envolvendo n = 1.000.000 de dados, podemos imaginar uma tabela de hashing com 2.000 entradas, onde temos uma diviso do espao de busca da ordem de n/2.000 de imediato. Aplicao imediata a arquivos -Os mtodos de hashing, tanto de endereamento aberto como fechado, podem ser utilizados praticamente sem nenhuma alterao em um ambiente de dados persistentes utilizando arquivos em disco.

As desvantagens podem ser: Dependncia da escolha de funo de hashing - Para que o tempo de acesso mdio ideal T(n) = c1.(1/b).n + c2 seja mantido, necessrio que a funo de hashing divida o universo dos dados de entrada em b conjuntos de tamanho aproximadamente igual. Tempo mdio de acesso timo somente em uma faixa - A complexidade linear implica em um crescimento mais rpido em relao a n do que as rvores, p.ex. Existe uma faixa de valores de n, determinada por b, onde o hashing ser muito melhor do que uma rvore, fora dessa faixa pior.

10.3 Funes Hash


Tem o objetivo de transformar o valor da chave de um elemento de dados em uma posio para este elemento na tabela hash. Chamada de funo de disperso ou espalhamento. Uma funo de hashing ideal deve satisfazer s seguintes condies: Produzir um nmero baixo de colises - Depende de se conhecer algo sobre a distribuio das chaves sendo acessadas. Ser facilmente computvel - Tipicamente, funes contendo poucas operaes aritmticas Ser uniforme - Idealmente, o nmero mximo de chaves que so mapeadas num mesmo ndice deve ser |N|/|M|.

10.3.1 Mtodo da Diviso


A funo hashing mais difundida o mtodo da diviso ou congruncia linear, a qual definida como sendo: H(K) = K mod N onde K a chave a ser transformada, N o nmero de possveis elementos da tabela e mod calcula o resto da diviso inteira de K por N. A funo mod pode ser substituda pela diviso por inteiro para conseguir o resto. Tomemos, ttulo de ilustrao, uma tabela que admita um mximo de 53 entradas e que tenham o campo chave apresentando valores no intervalo de [0..1000]. Tomemos tambm a ttulo de exemplo a seguinte funo de clculo de endereo: H(K) = (K mod 53) + 1 Portanto, a funo H recebe um argumento que um valor entre 0 e 1000, e calcula um endereo entre 1 e 53. A seguir, consideramos os seguintes valores de chave e os endereos correspondentes. Chave 383 487 235 527 510 320 203 108 563 500 646 103 63

102

Endereo

12

10

23

50

33

44

33

23

10

50

10

Figura 42 - Exemplo hashing

Neste exemplo, notamos que o endereo 33 gerando para as chaves 510 e 563, enquanto o endereo 10 gerando para as chaves 487, 646 e 63. Para chaves numricas basta dividir pelo tamanho da tabela. Abaixo o algoritmo que utiliza esta funo.
Algoritmo DivisaoInteira Constante TAMANHO = 10 Variveis chave : Inteiro Sub-rotina divisaoInteira ( _chave : Inteiro ) : Inteiro Inicio Retorne (_chave MOD TAMANHO) + 1; Fim Inicio Leia(chave) Escreva("O endereo para chave " + chave + " "+ divisaoInteira(chave)) Fim.

Para chaves alfanumricas necessrio converter cada caractere para nmero, soma-los e dividir pelo tamanho da tabela.
Algoritmo DivisaoInteiraAlfa Constante TAMANHO = 10 Variveis chave : Literal Sub-rotina divisaoInteiraLiteral ( _chave : Literal ) : Inteiro Variveis i,soma : inteiro Incio soma 0 Para i de 1 at tamanho(_chave) faa soma soma + ord(_chave[i]) Fim_Para Retorne (soma MOD TAMANHO) + 1; Fim Inicio Leia(chave) Escreva("O endereo para chave " + chave + " "+ divisaoInteira(chave)) Fim.

10.3.2 Mtodo da Dobra


Tambm conhecido como Folding ou Desdobramento, neste mtodo, as chaves so interpretadas como uma seqncia de dgitos escritos num pedao de papel. Ele consiste em "dobrar" esse papel, de maneira que os dgitos se superponham sem levar em considerao o "vai um" como mostra a figura abaixo.

103

Figura 43 - Mtodo da Dobra

O processo repetido at que os dgitos formem um nmero menor que o tamanho da tabela hash. importante destacar que o mtodo da dobra tambm pode ser usado com nmeros binrios. Nesse caso, ao invs da soma, deve-se realizar uma operao de "ou exclusivo", pois operaes de "e" e de "ou" tendem a produzir endereos-base concentrados no final ou no incio da tabela.

10.3.3 Mtodo da Multiplicao


Pode ser chamado tambm de mtodo da congruncia linear multiplicativo. Neste mtodo, a chave pode ser multiplicada por ela mesma ou por uma constante, e ter o seu resultado armazenado em uma palavra de memria de s bits. Considere que o nmero de bits necessrios para enderear uma chave na tabela hashing seja r. Dessa forma, para compor o endereo-base de uma chave, descartam-se os bits excessivos da extrema direita e da extrema esquerda da palavra. No exemplo abaixo, separamos os 4 bits centrais da palavra chave, pois a tabela hashing tem tamanho 16.

Figura 44 - Mtodo da Multiplicao

Tambm conhecido por meio do quadrado.

104

10.4 Tratamento de Colises


J foi observado que o mesmo endereo base pode ser encontrado para chaves diferentes, como resultado da funo de hash, o que chamado uma coliso. Define-se como fator de carga de uma tabela de hashing o valor a = N/M, onde N o nmero de chaves armazenadas e M o tamanho da tabela. Um mtodo para diminuir colises , ento, reduzir o fator de carga; medida que este cresce a possibilidade de ocorrerem colises tambm cresce. Existem dois mtodos bsicos para tratar colises: Endereamento Livre ou Aberto, onde havendo uma coliso, um novo ndice ser calculado, seja por outra funo hash definida, seja pela busca de um endereo livre. Sendo este endereo na prpria tabela. Na pesquisa de uma chave, ao tratar a colises em uma tabela por endereamento livre, podemos ter que procurar atravs de vrias funes hash, at encontr-la. Encadeamento, esse mtodo usa tanto funes hash quanto listas lineares. Onde todas as chaves que forem mapeadas para a mesma posio so armazenadas em uma lista encadeada.

10.4.1 Hashing com Tentativas Lineares


Esse mtodo de endereamento livre resolve colises tentando sempre a prxima posio na tabela (E + 1) at que ou a chave ou um elemento livre seja encontrado. Para que esse mtodo funcione para todos os casos, usaremos o conceito de tabela circular, onde o primeiro elemento segue o ltimo logicamente. H(K) = K MOD N RH(K) = (K + 1) MOD N Exemplo: Tamanho da Tabela = 7 Inserir 67=>H(67) = Inserir 72=>H(72) = RH(65) = Inserir 65=>H(66) = Inserir 86=>H(86) = RH(87) = RH(88) = Inserir 69=>H(69) = Inserir 83=>H(83) = RH(84) = 67 72 65 66 86 87 88 69 83 84 MOD MOD MOD MOD MOD MOD MOD MOD MOD MOD 7 7 7 7 7 7 7 7 7 7 = = = = = = = = = = 4 2 2 3 2 3 4 6 6 0 //Sem coliso //Sem coliso //Coliso aplicar //Sem coliso //Coliso aplicar //Coliso aplicar //Sem coliso //Sem coliso //Coliso aplicar //Sem coliso

hashing linear hashing linear hashing linear

hashing linear

10.4.2 Hashing Duplo


Nesse mtodo de endereamento livre, similar aos das tentativas lineares, o algoritmo resolve os problemas de coliso atravs do de duas funes hashing H e H2. A primeira chamada de hashing primrio utilizada na primeira vez para determina a posio na qual a chave deve ficar. Se a posio estiver ocupada a funo RH ser chamada sucessivas vezes at que uma posio vazia seja encontrada. Para o primeiro clculo: H(K) = K MOD N Caso haja coliso, utilizamos o resultado de H0(K) para calcular H1(K), que pode ser definida como: H2(K) = 1 + (K MOD (N-1)) Em seguida calculamos a funo re-hashing como sendo: RH(i,K) = (i + H2(K)) MOD N, 1 < i <= N -1

105

Exemplo: Tamanho da Tabela = 10 Inserir 35=>H(35) = Inserir 65=>H(65) = H2(65) = RH(5,65) = 35 MOD 10 = 5 //Sem coliso 65 MOD 10 = 5 //Coliso aplicar hashing duplo 1 + (65 MOD (10-1)) = 3 (5+3) MOD 10 = 8 //Posio de insero

10.4.3 Hashing Quadrtico


Nesse mtodo de endereamento livre, o algoritmo resolve colises usando uma funo quadrtica para incremento do ndice que ser usado a cada tentativa. H = K MOD N RH(i,K) = (H + i^2) MOD N, i > 0 Exemplo: Tamanho da Tabela = 10 Inserir 35=>H(35) = 35 MOD 10 = 5 //Sem coliso Inserir 65=>H(65) = 65 MOD 10 = 5 //Coliso hashing quadratico RH(5,65) = (5+5^2) MOD 10 = 0 //Posio de insero

10.4.4 Hashing com Encadeamento


A funo hashing fornece a localizao para uma chave a ser inserida na tabela. Esse elemento conter um registro e um ponteiro para uma lista encadeada com todos os registros que tenham tambm aquela localizao mapeada pela mesma funo hashing. Um campo a mais para o encadeamento deve ser adicionado a cada n. A essa lista damos o nome de rea de overflow. As listas podem se encontrar no exterior da tabela ou compartilhar o mesmo espao da tabela.

10.4.4.1 Encadeamento Externo


Cada posio da tabela de disperso armazena um ponteiro para o incio desta lista encadeada.
Endereo

1
2

nulo 320 nulo 487 nulo 383 nulo 203 nulo nulo
Figura 45 Encadeamento Externo

108

nulo

10

646

63

nulo

12

nulo

44 53

nulo

106

10.4.4.2 Encadeamento Interno


Em algumas aplicaes, no desejvel a manuteno de uma estrutura exterior tabela de hashing. Nessa situao, ainda possvel resolver o problema de colises mediante o emprego de listas encadeadas, desde que estas compartilhem o mesmo espao de memria que a tabela de disperso. O encadeamento interior prev a diviso da tabela T em duas zonas, uma de endereos base, de tamanho N, e outra reservada aos sinnimos, de tamanho S (naturalmente, N + S = M). Os valores N e S so fixos. Assim sendo, a funo de disperso deve obter endereos base na faixa [1, N] apenas. Os endereos de N+1 at M correspondente a S sendo uma rea comum chamada de rea de overflow.
Endereo

1 2 10 12 44 53 54 55 56
108 646 63 487 320

54

55

383

203

56 -

Figura 46 Encadeamento Interior

107

11. Bibliografia
AZEREDO, P.A. Mtodos de Classificao de Dados e anlise de suas complexidades. 1. ed. Rio de Janeiro: Campus, 1996. DEITEL, H. M. ; DEITEL, P.J. Java Como Programar. 3. ed. Porto Alegre: Bookman, 2001. CELES, W.; CERQUEIRA, R. Introduo a Estrutura de Dados: com tcnica de programao em C. Rio de Janeiro: Elsevier, 2004. FARRER, H.; BECKER, C.G.; FARIA, E.C.; CAMPOS FILHO, F.F.; SANTOS, M.A.; MAIA, M.L. Pascal Estruturado. 2. ed. Rio de Janeiro: Livros Tcnicos e Cientficos, 1986. GOODRICH, M. T. Estrutura de Dados e algoritmos em Java. 2. ed. Porto Alegre: Bookman, 2002. NELSON, M. The Data Compression Book. 1. ed. San Mateo: M&T Books, 1992. SWAIT JR, J. D. Fundamentos Computacionais, algoritmos e estrutura de dados. 1. ed. So Paulo: Makron, McGraw-Hill, 1991. VELOSO, P. ; SANTOS, C. ; AZEREDO, P. ; FURTADO, A. Estrutura de Dados. Rio de Janeiro: Campus, 1986. VILLAS, M.V. ; FERREIRA, A.G.M. ; LEROY, P.G. ; MIRANDA, C. ; BOCKMAN, C.L. Estrutura de Dados: Conceitos e Tcnicas de Implementao. Rio de Janeiro: Campus, 1993. ZIVIANI, N. Projeto de Algoritmos : com Implementaes em Pascal e C. 3. ed. So Paulo: Pioneira Informtica, 1996.

Potrebbero piacerti anche