Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
v1.1 2012A
Sumrio
1. 2. Introduo ............................................................................................................................................................ 4 Tipos de Dados ..................................................................................................................................................... 5
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.
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.
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
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.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
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;
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.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
Aps a incluso do novo nome, novas incluses seriam impossveis, visto que no mais haveria espao disponvel para tanto.
13
: : : :
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
: : : :
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
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.
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.
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
: : : :
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
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.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.
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.
: : : :
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.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.
dado
proximo
dado
proximo
dado
proximo
31
: 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
fim
d ado proximo d ado proximo
d ado
proximo
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
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
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
45
dado
proximo
dado
proximo
dado
proximo
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.
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.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.
51
: 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
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:
: 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
67
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
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.
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
1)soma n=3
2)soma n=2
3)soma
4)soma
Figura 20 - Teste de Mesa para N=4 (somatrio dos 4 primeiros nmeros inteiros)
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
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(2) 1
Fib(2) 1
Fib(1) 1
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.
75
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
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
Sada
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:
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
E
FOLHA
NVEL 3
G
FOLHA
H
FOLHA
I
FOLHA SUBRVORE
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
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 -
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
82
A B C
D G H E F I
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.
83
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)
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:
85
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.
42-51-19-37-42-86-71-10-75-22-31-42
Resulta na rvore binria colocada abaixo:
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).
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:
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.
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.
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
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
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.
: 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
: 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
E = H(K)
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
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.
102
Endereo
12
10
23
50
33
44
33
23
10
50
10
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.
103
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.
104
hashing linear
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
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
1 2 10 12 44 53 54 55 56
108 646 63 487 320
54
55
383
203
56 -
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.