Sie sind auf Seite 1von 102

Mariela Ins Corts

Estrutura de Dados

2010
Copyright 2010. Todos os direitos reservados desta edio SECRETARIA DE EDUCAO A DISTNCIA
(SEAD/UECE). Nenhuma parte deste material poder ser reproduzida, transmitida e gravada, por qualquer
meio eletrnico, por fotocpia e outros, sem a prvia autorizao, por escrito, dos autores.

EXPEDIENTE

Design instrucional
Antonio Germano Magalhes Junior
Igor Lima Rodrigues
Pedro Luiz Furquim Jeangros

Projeto grfico
Rafael Straus Timb Vasconcelos
Marcos Paulo Rodrigues Nobre

Coordenador Editorial
Rafael Straus Timb Vasconcelos

Diagramao
Marcus Lafaiete da Silva Melo
Francisco Jos da Silva Saraiva

Ilustrao
Marcos Paulo Rodrigues Nobre

Capa
Emilson Pamplona Rodrigues de Castro
PRESIDENTE DA REPBLICA
Luiz Incio Lula da Silva
MINISTRO DA EDUCAO
Fernando Haddad
SECRETRIO DE EDUCAO A DISTNCIA
Carlos Eduardo Bielschowsky
DIRETOR DO DEPARTAMENTO DE POLTICAS EM EDUCAO A DISTNCIA DPEAD
Hlio Chaves Filho
SISTEMA UNIVERSIDADE ABERTA DO BRASIL
Celso Costa
GOVERNADOR DO ESTADO DO CEAR
Cid Ferreira Gomes
REITOR DA UNIVERSIDADE ESTADUAL DO CEAR
Francisco de Assis Moura Araripe
VICE-REITOR
Antnio de Oliveira Gomes Neto
PR-REITORA DE GRADUAO
Josefa Lineuda da Costa Murta
COORDENADOR DA SECRETARIA DE EDUCAO A DISTNCIA
Antonio Germano Magalhes Junior
COORDENADOR GERAL UAB/UECE
Francisco Fbio Castelo Branco
COORDENADORA ADJUNTA UAB/UECE
Josete de Oliveira Castelo Branco Sales
COORDENADOR DA LICENCIATURA EM INFORMTICA
Joaquim Celestino Junior
COORDENADOR DE TUTORIA E DOCNCIA DA LICENCIATURA EM INFORMTICA
Jorge Lus de Castro e Silva
Sumrio
Apresentao ....................................................................................................................... 7

Unidade 1
Introduo Complexidade de Algoritmos ........................................................................... 9
Captulo 1 - Introduo ...................................................................................................... 11
O que anlise de algoritmos? ............................................................................................. 12
Captulo 2 - Medidas de Complexidade ............................................................................. 14
Comparao entre algoritmos ..............................................................................................15

Unidade 2
Representao dos Dados..................................................................................................... 23
Captulo 1 - Modelagem Conceitual................................................................................... 25
Tipo de dados .......................................................................................................................25
Tipo abstratos de dados ........................................................................................................28
Critrios para a escolha da estrutura de dados adequada....................................................31

Unidade 3
Listas .................................................................................................................................... 35
Captulo 1 - Listas ............................................................................................................... 37
Introduo.............................................................................................................................37
Denio do TAD Lista...........................................................................................................37
Implementao do TAD Lista usando alocao esttica ............................................................... 38
Implementao do TAD Lista usando alocao dinmica ............................................................. 43
Variaes sobre o TAD Lista ........................................................................................................... 49
Captulo 2 - Pilhas .............................................................................................................. 51
Implementaes do TAD Pilha usando vetores ..................................................................... 52
Implementao do TAD Pilha usando ponteiros ................................................................... 54
Captulo 3 - Filas ................................................................................................................. 57
Implementao do TAD Fila usando vetores ......................................................................... 57
Implementao do TAD Fila usando ponteiros ..................................................................... 60

Unidade 4
rvores ................................................................................................................................ 65
Captulo 1 - rvores ........................................................................................................... 67
rvore binria ......................................................................................................................68
Captulo 2 - rvore binria de busca .................................................................................. 71
Denio do TAD rvore Binria de Busca ........................................................................... 71
Implementao do TAD rvore Binria de Busca ................................................................. 72
Ordens de percurso em rvores binrias....................................................................................... 77
Relao entre o nmero de ns de uma rvore
binria e sua altura......................................................................................................................... 79
Captulo 3 - rvores AVL...................................................................................................... 81

Unidade 5
Busca avanada .................................................................................................................... 89
Captulo 1 - Tabela de disperso......................................................................................... 91
A funo de disperso............................................................................................................92
Estratgias para resoluo de colises................................................................................... 94
Encadeamento .............................................................................................................................. 94
Tcnicas de sondagem.................................................................................................................... 95
Captulo 2 - Busca digital..................................................................................................... 97
rvore digital.........................................................................................................................98
Captulo 3 - Estruturas autoajustveis................................................................................ 100
Listas autoajustveis..............................................................................................................100
O constante aumento da complexidade dos sistemas e suas demandas computa-
cionais relacionadas a tempo e espao, impem o desafo de projetar solues algortmi-
cas cada vez mais efi cientes. Neste contexto, as estruturas de dados e seus algoritmos
tm um papel fundamental uma vez que constituem os blocos construtores utilizados
na resoluo dos mais diversos problemas em todas as areas da computao.
O objetivo do presente livro apresentar de forma clara e amigvel diferentes
estruturas de dados e seus algoritmos de manipulao, analisando a estratgia mais
efi ciente para a sua implementao, em termos de complexidade. Esta anlise envolve
a utilizao de tcnicas de projeto associadas a tcnicas de programao, as quais so
adequadas s caracteristicas da aplicao especfi ca.
O livro est organizado em cinco unidades. As primeiras fornecem as bases ne-
cessrias para a anlise e o projeto de uma boa soluo algortmica incluindo concei-
tos bsicos sobre complexidade, tipos e estruturas de dados. A Unidade 3 apresenta o
conceito central de Listas, a partir do qual duas importantes e amplamente utilizadas
estruturas so derivadas: Pilhas e Filas.
A Unidade 4 apresenta a estrutura de rvore, sua conceituao, implementao
e algoritmos de manipulao bsicos. Mais especifi camente, nesta unidade so explo-
radas as rvores Binrias de Busca analizando suas caractersticas e as implicaes
em relao efi cincia. Neste contexto, a fundamentao e funcionamento das rvores
balanceadas (AVL) so apresentados. Finalmente, na Unidade 5 so descritas as tcni-
cas avanadas de pesquisa aplicadas sobre estruturas de dados especfi cas, tais como
tabelas de disperso, busca digital e estruturas autoajustveis.
O contedo apresentado destina-se principalmente para professores e alunos de
graduao em Cincias da Computao ou reas afi ns, fornecendo um embassamento
terico e uma clara noo das estratgias a serem seguidas na implementao dos
algoritmos para a manipulao efi ciente das estruturas de dados mais amplamente
utilizadas.

A autora
Unidade

1
Introduo Complexidade
de Algoritmos

Objetivos:
Nesta unidade introduzido o conceito de complexidade de algoritmos. Este
conceito central na Cincia da Computao, uma vez que possibilita avaliar
e comparar solues algortmicas, fornecendo os insumos necessrios para
determinar qual o algoritmo mais adequado para resolver determinada classe
de problemas.
Captulo 1
Introduo

Um algoritmo determina um conjunto de regras no ambguas as


quais especifi cam, para cada entrada, uma seqncia fi nita de operaes,
gerando como resultado uma sada. O algoritmo representa uma soluo
para um problema se, para cada entrada, gera uma resposta correta, sem-
pre que dispor de tempo e memria sufi cientes.
Um algoritmo pode ser implementado atravs de diferentes progra-
mas. Ou seja, diferentes implementaes podem ser propostas a partir de
um nico algoritmo. Esta situao nos coloca na difi culdade de escolher
qual a melhor soluo para o problema especfi co. Assim sendo, apenas
resolver o problema parece no ser sufi ciente uma vez que diferentes solu-
es podem ser idealizadas a partir de algoritmos, para a resoluo de um
nico problema. Neste contexto, se torna necessrio um mecanismo que
permita determinar se uma soluo melhor do que uma outra, de forma
a fornecer uma ferramenta de apoio desio em relao qualidade das
solues propostas.
Programa codifi ca um al-
De forma geral, a qualidade de um programa depende do ponto de vis- goritmo para ser executa-
ta. Por um lado, o usurio determina a qualidade de um programa atravs do no computador resol-
de critrios, tais como: vendo um problema.
fundamental que o pro-
Facilidade de uso e entendibilidade da interface do programa levan- grama produza a soluo
do em conta diferentes nveis de experincia. com dispndio de tempo e
memria: Importncia de
Compatibilidade do programa com outros programas ou verses de Projeto e Analise de Algo-
programas, de forma a facilitar a troca de informao com outros ritmos.
sistemas existentes.
Desempenho, em relao velocidade de execuo e tempo de res-
posta.
Quantidade de memria utilizada pelo programa durante a sua exe-
cuo, aspecto que pode se tornar um fator limitante.
Os ltimos dois itens esto diretamente ligados quantidade de dados
a serem processados, ou seja, ao tamanho da entrada.
Por outro lado, critrios que podem ser determinantes desde o ponto
de vista da organizao desenvolvedora incluem:
Portabilidade do cdigo entre diferentes plataformas.
Documentao e padronizao do cdigo.
Facilidade de evoluo e manuteno.
Reusabilidade do cdigo, permitindo que pores de um programa
sejam reaproveitadas para desenvolver outros produtos, aumentan-
do a produtividade.

ESTRUTURA DE DADOS 11
A correta avaliao destes critrios infl uenciada por diversos fatores,
tais como: caractersticas do hardware, sistema operacional, linguagens e
compiladores, plataforma, etc. Estes fatores so considerados acidentais
uma vez que no esto diretamente relacionados qualidade da soluo.
Em contrapartida, os fatores essenciais so inerentes soluo e determi-
nantes para a sua qualidade. O tempo gasto e o espao fsico na memria
so considerados fatores essenciais. Consequentemente preciso de um
mtodo formal para medir o tempo e a memria requeridos pelo algoritmo,
independentemente das caractersticas de plataforma de hardware e sof-
tware sendo utilizadas.

O que anlise de algoritmos?


A anlise de algoritmos o corao da Cincia da Computao e tem
por objetivo estabelecer medidas de desempenho dos algoritmos, com vis-
tas gerao de algoritmos cada vez mais efi cientes. Adicionalmente for-
nece fundamentos para a escolha do melhor algoritmo para a resoluo de
um problema especfi co, com base na sua complexidade computacional.
O tempo de execuo e o espao de memria alocado so os dois
fatores principais que determinam a complexidade computacional de
uma algoritmo.
Complexidade temporal consiste no nmero (aproximado) de instru-
es executadas.
Complexidade espacial consiste na quantidade de memria utilizada.
De forma geral, tanto a complexidade temporal quanto a espacial po-
dem ser descritas por funes que tm como parmetro principal o tama-
nho da entrada sendo processada. Como exemplos temos que:
Ordenar 100.000 elementos leva mais tempo que ordenar 10 ele-
mentos.
A abertura de um editor de textos leva mais tempo e consume mais
memria quando aberto com um arquivo grande do que com um
arquivo pequeno.
Alm do tamanho da entrada, as caractersticas apresentadas na
organizao dos dados, tambm podem infl uenciar na efi cincia de um
algoritmo em relao a uma outra soluo. Por exemplo, o desempenho
de um algoritmo especfi co para ordenar um conjunto onde os dados se
encontram parcialmente ordenados pode ser muito diferente se utilizado
para ordenar um conjunto de dados totalmente desordenados, conside-
rando conjuntos de igual tamanho. Logo importante estabelecer de que
forma o tamanho e caractersticas da entrada podem infl uenciar no com-
portamento do algoritmo.
Em alguns casos, se o algoritmo no recursivo, no contem itera-
es e no usa algoritmos com essas caractersticas, o nmero de passos
A principal caracterstica
de um algoritmo recursivo
necessrios pode ser independente do tamanho da entrada, e consequen-
a ocorrncia de chama- temente a complexidade temporal constante.
das a ele prprio.
Para avaliar a complexi-
Um exemplo de algoritmo com estas caractersticas o algoritmo que
dade de um algoritmo re- imprime HELLO WORD, que possui complexidade constante.
cursivo preciso analisar
quantas vezes a funo
vai ser chamada, e quan-
tas operaes acarretam
cada chamada.

12 ESTRUTURA DE DADOS
#include <stdio.h>
main() {
for(;;) {
Printf (Hello Word!\n);
}
}
Considerando que impossvel fazer uma predio exata do tempo e
memria a serem utilizados a estratgia consiste em estabelecer uma apro-
ximao, com base em conceitos e modelos matemticos.

1. Descreva com suas palavras a relao entre os conceitos de algoritmo e


programa.
2. Determine em quais casos e de que forma as especifi caes a seguir
podem depender do tamanho ou organizao dos dados da entrada. Jus-
tifi que a sua resposta.
a. Procurar o maior elemento em uma sequncia.
b. Modifi car o contedo de uma varivel.
c. Imprimir o contedo de uma sequncia de elementos.
d. A partir dos dados de uma pessoa: nome, data de nascimento, sexo,
determinar se a pessoa maior de 18 anos.

ESTRUTURA DE DADOS 13
Captulo 2
Medidas de Complexidade

De forma geral, a complexidade de um algoritmo determinada pela


quantidade de trabalho requerido sobre um determinado tamanho da en-
trada. O trabalho depende diretamente do nmero de operaes bsicas
efetuadas.
Considere o problema de estabelecer se um determinado elemento
pertence a um conjunto de 100 elementos. A soluo mais simples para
este problema envolve uma pesquisa sequencial onde o elemento procu-
rado comparado a cada um dos elementos pertencentes ao conjunto. O
nmero de comparaes realizadas ir depender dos diversos cenrios
possveis. A principio podemos analizar duas situaes: o elemento en-
contrado na primeira comparao realizada ou, o elemento no existe no
conjunto. No primeiro caso seria preciso somente uma comparao, en-
quanto que no ltimo caso todo o conjunto precisaria ser checado, envol-
vendo, portanto 100 comparaes.
A partir das situaes apresentadas podemos concluir que a comple-
xidade de um algoritmo pode ser estabelecida utilizando uma estratgia
pessimista ou mxima, ou otimista ou mnima. No primeiro caso, o algo-
ritmo analisado levando em conta o cenrio mais adverso, o que normal-
mente ir resultar no maior tempo de execuo. Este critrio normalmente
o mais utilizado uma vez que estabelece uma cota ou limite superior no
tempo requerido. Em oposio a esta abordagem, a complexidade otimis-
ta ou mnima obtida quando o problema analisado levando em conta
um cenrio ideal demandando, portanto, menos tempo de execuo. Pode
ainda ser considerado um caso mdio ou esperado, correspondente m-
dia dos tempos de execuo de todas as entradas de tamanho n. Estas
estratgias podem ser utilizadas tanto para estabelecer a complexidade
espacial quanto temporal dos algoritmos.
A anlise para o clculo destas medidas pode ser realizada empiri-
camente, isto , com base na experincia e na observao prtica, exclusi-
vamente, sem se basear em nenhuma teoria. No entanto, a medio obtida
pode ser influenciada por fatores acidentais referentes plataforma espe-
cfica, como por exemplo, a capacidade de processamento do computador
sendo utilizado. Consequentemente, a execuo de um algoritmo em um
determinado computador pode ter um desempenho diferente medio
resultante a partir da execuo do mesmo algoritmo em um outro compu-
tador com caractersticas diferentes. Estas possveis divergncias tornam
a abordagem baseada na medio emprica pouco confivel.

14 ESTRUTURA DE DADOS
1. Determine o caso otimista e o caso pessimista a partir das seguintes
especifi caes:
a. Encontrar o maior elemento de um vetor (desordenado) de inteiros.
b. Encontrar o maior elemento de um vetor ordenado de forma decres-
cente de inteiros.
c. Remover um dado elemento de um vetor de inteiros.
d. Idem anterior considerando um vetor ordenado em forma crescente.
2. Considere o problema de encontrar o maior elemento de um vetor de
inteiros. O algoritmo a seguir apresenta uma soluo simples para o
problema.
int Max (A Vetor){
int i, Temp;

Temp = A[0];
for (i := 1; i < n; i++)
if (Temp < A[i]) Temp := A[i];
return (Temp);
}
a. Determine o nmero de comparaes realizadas entre os elementos
de A, considerando que A contem n elementos.
b. Descreva quais so as situaes que representam o melhor caso, o
pior caso e o caso mdio para o algoritmo.

Comparao entre algoritmos


Como dito anteriormente, para um dado problema podem existir di-
versos algoritmos possveis. Cabe ao programador analisar as possibilida-
des e escolher o algoritmo mais adequado utilizando como critrio bsico a
sua complexidade.
Uma abordagem amplamente adotada para analizar a complexidade
de algoritmos baseada na anlise encima das operaes fundamentais
que compem o algoritmo, a partir das quais derivada uma funo custo
modelando o comportamento que o algoritmo ir a adotar de acordo com os
dados de entrada fornecidos. Em particular, quando consideradas entradas
sufi cientemente pequenas, o custo reduzido, mesmo no caso de algorit-
mos inefi cientes. J para tamanhos de entrada sufi cientemente grandes, a
escolha por um determinado algoritmo pode ser um problema crtico. Logo,
a anlise de algoritmos interessante para valores grandes da entrada, ou
seja, no caso de algoritmos que manipulam grandes quantidades de dados.

ESTRUTURA DE DADOS 15
O estudo da complexidade consiste em determinar a ordem de magni-
tude do nmero de operaes fundamentais realizadas pelo algoritmo, des-
critas a partir da defi nio da funo custo. A partir desse estudo possvel
realizar a comparao do comportamento assinttico atravs da anlise
dos grficos correspondentes.

Comportamento observa-
do de f(n) quando n tende
a infi nito.

A comparao entre funes com base no critrio de comportamento


assinttico consiste no estudo do crescimento de funes para valores gran-
des de n, no nosso caso, referente ao tamanho da entrada. A partir dessa
anlise, as funes so classifi cadas em ordens, onde cada ordem agru-
pa funes de crescimento semelhante. O algoritmo assintoticamente mais
eficiente o melhor para todas as entradas. Neste contexto, uma funo
considerada uma cota assinttica superior ou domina assintoticamente ou-
tra, quando cresce mais rapidamente do que outra: grafi camente, o grfi co
da primeira funo fi ca por cima da segunda a partir de certo ponto m. No
caso geral, nem sempre possvel determinar se f (n) < g (n).
Sejam f e g as duas funes de custo que queremos comparar:
1. Se f sempre inferior a g, ou seja, o grfi co de f fi ca sempre por bai-
xo do grfi co de g, ento a escolha para o algoritmo correspondente
a f bvia.
1. Se f s vezes inferior a g, e vice-versa, e os grfi cos de f e g se inter-
ceptam em um nmero infi nito de pontos. Neste caso, consideramos
que h empate, e a funo custo no ajuda a escolher um algoritmo.
2. Se f s vezes g inferior a g, e vice-versa, e os grfi cos de f e g se
cortam em um nmero fi nito de pontos. Portanto, a partir de certo
valor de n, f sempre superior a g, ou sempre inferior. Neste caso,
consideramos melhor aquele algoritmo que inferior ao outro para
grandes valores de n.

As funes mais comumente encontradas em anlise de programas,


considerando n como tamanho da entrada, so:
f(n) = k Constante
f(n) = k . n Linear
f(n) = n . log n Logartmica
f(n) = k . n2 Quadrtica
f(n) = k . n3 Cbica
f(n) = nk Polinomial
f(n) = k . en Exponencial
A fi gura a seguir representa a ordem de crescimento das funes mais
comumente utilizadas na representao da complexidade dos algoritmos.
Comparativamente podemos concluir que, na medida em que o tamanho

16 ESTRUTURA DE DADOS
da entrada n aumenta, a funo linear n cresce mais rapidamente do que
a funo log(n), que por sua vez cresce mais lentamente do que a funo
quadrtica n 2, e assim por diante.

Sempre possvel determinar a taxa de crescimento relativo de duas


funes f(n) e g(n) calculando Lim f(n) / g(n)
x
A partir deste clculo existem os seguintes valores possveis:
0, ento g(n) limite superior para = f(n)
c, ento f(n) e g(n) tem complexidades equivalentes
infi nito, ento f(n) limite superior para g(n)
No caso de funes oscilantes, como o caso de sen(n) ou cos(n), nenhu-
ma afi rmao pode ser feita.

1. Considere os algoritmos A e B com complexidades:


CA(n) = 1000 n2
CB(n) = 0, 1 n3
Determine a partir de qual valor de n, CB domina assintoticamente CA?
2. Para um determinado problema P, temos algoritmos A, B, C, e D com
as seguintes complexidades.
CA(n) = 100 n log n
CB(n) = 1000 n
CC(n) = 4 n2
CD(n) = 10 5 en
Classifi car os algoritmos do melhor at o pior, em termos de complexi-
dade, sempre considerando valores grandes da varivel n (tamanho da
entrada). Justifi que.

ESTRUTURA DE DADOS 17
A notao utilizada para denotar a dominao assinttica foi introdu-
zida por Knuth em 1968. De acordo com esta notao, a expresso g(n) =
O(f(n)) expressa que f(n) domina assintticamente g(n). A expresso pode ser
lida da seguinte forma: g(n) da ordem no mximo de f(n). As defi nies a
seguir formalizam a notao de Knuth.
A notao mais comumente usada para medir algoritmos O, uma vez
que determina um limite superior da complexidade:

De nio. A funo custo C(n) O(F(n)) se existem constantes positivas c e


m tais que:
Donald Ervin Knuth, na- C(n) c . F(n), quando n m
cido em Milwaukee, em
10 de Janeiro de 1938,
A defi nio acima afi rma que existe algum ponto m a partir do qual
um cientista computacio-
nal de renome e professor c . F(n) sempre pelo menos to grande quanto C(n). Assim, se os fatores
emrito da Universidade constantes so ignorados, F(n) pelo menos to grande quanto C(n).
de Stanford. o autor do
livro The Art of Computer Como exemplo, seja g(n) = (n + 1)2 . Logo, g(n) O(n2), quando m = 1 e
Programming, uma das c = 4, uma vez que (n + 1)2 4n2 para n 1.
principais referncias da
Cincia da Computao. Em outras palavras, quanto dizemos que C(n) = O(F(n)) estamos ga-
considerado o criador rantindo que a funo C(n) no cresce mais rpido do que F(n). Assim, F(n)
do campo de Anlise de um limite superior para C(n).
Algoritmos e fez diversas e
importantes contribuies De forma geral, os termos de menor peso e os fatores podem sempre
a vrios ramos da teoria ser eliminados uma vez que para valores grandes da variaveis, estes com-
da computao
ponentes se tornam despresiveis. Assim O(4n3 + 10n2) e O(n3) so sinni-
mos, mas o segundo termo mais preciso.
Se um algoritmo O(1) signifi ca que o nmero de operaes funda-
mentais executadas limitado por uma constante.
Intuitivamente, se g(n) = 2 n2 , ento g(n) = O(n4), g(n) = O(n3) e g(n) =
O(n ). Todas as respostas so tecnicamente corretas, mas a menor a me-
2

lhor resposta.

Outras definies formais


Limite inferior:
A notao usada para especifi car o limite inferior da complexi-
dade de um algoritmo.
Complexidade exata:
A notao usada para especifi car exatamente a complexidade
de um algoritmo.
Limite superior estrito: o
Enfi m a notao o usada para especifi car que a complexidade de
um algoritmo e inferior estritamente a certa funo.

1. Suponha g(n) = n e f(n) = n2, demostre qual das seguintes afi rmaes
verdadeira:
a. f(n) = O(g(n))
b. g(n) = O(f(n))

18 ESTRUTURA DE DADOS
2. Determine a ordem mxima para as seguintes funes e justifique a sua
resposta detalhando os valores de c e n adequados.
a. g(n) = 3n3 + 2n2 + n
b. h(n) = n2 + n + 1

Operaes com a notao O


Algumas operaes que podem ser realizadas com a notao O so
apresentadas a seguir:
f(n) = O(f(n))
c . O(f(n)) = O(f(n)), onde c uma constante
O(f(n)) + O(f(n)) = O(f(n))
O(O(f(n))) = O(f(n))
O(f(n)) + O(g(n)) = O(max (f(n), g(n)))
O(f(n)) . O(g(n)) =O(f(n) . g(n))
f(n ). O(g(n)) = O(f(n) . g(n))
Estas operaes foram demostradas matematicamente na literatura
e tem aplicao direta para o clculo do tempo de execuo de (trechos de)
programas. Por exemplo, a regra da soma, O(f(n)) + O(g(n)) pode ser utili-
zada para calcular o tempo de execuo de uma sequncia de trechos ou
sentenas de programas. Aplicando essa regra, somente ser considerado o
trecho que tiver atribudo o custo mximo dentre os trechos ou sentenas
considerados no sumatrio.
Aplicando a abordagem de dividir para conquistar, a complexidade de
um algoritmo pode ser determinada a partir da complexidade das suas par-
tes. De forma geral, a anlise da complexidade feita em forma particular
para cada algoritmo, mas existem conceitos gerais que s dependem das
estruturas algortmicas ou comandos de controle utilizados no algoritmo:
1) Sequncia ou conjuno um tipo de comando que, no fluxo lgico
do programa, executado e o controle passa para o prximo co-
mando na sequncia.
A anlise da complexidade neste caso envolve a aplicao da
regra da soma para a notao O com base na complexidade dos
comandos.
2) Seleo ou disjuno um tipo de comando que, no fluxo de exe-
cuo permite que desvios possam ser feitos a partir do resultado
da avaliao de uma condio, executando um bloco de comandos
e outros no.
A anlise sempre feita considerando o pior caso. Consequen-
temente, na avaliao da complexidade considerado o desvio
que envolve a execuo do bloco de comandos mais custoso, a
partir da avaliao da condio. Adicionalmente, a avaliao
da condio consome tempo constante
3) Repetio um tipo de comando que, no fluxo de execuo do pro-
grama, permite que um bloco de comandos seja repetido enquanto
uma condio satisfeita.
Alm da checagem da condio (O(1)), o custo de um comando
de repetio envolve o custo do bloco envolvido, multiplicado
pelo nmero de vezes que ser executado, no pior caso. Vale

ESTRUTURA DE DADOS 19
ressaltar que pode existir aninhamento de comandos de repe-
tio. Neste caso a anlise feita de dentro para fora. O lao
pode ser defi nido (for) ou indefi nido (while).
4) Um comando de atribuio possibilita que um valor possa ser atri-
budo a uma varivel.
Um comando de atribuio consome tempo constante.

Por exemplo, dado um vetor v de nmeros inteiros de tamanho n, re-


tornar o maior elemento deste vetor.
1: int Maximo (int v[], int n){
2: int i: n;
3: int max;
4:
5: if n = 0 error ( Vetor vazio )
6: else {
7: max = v[0];
8: for (i = 1; i < n; i++)
9: if v[i] > max then max = v[i];
10: }
11: return max;
12:}

O nmero n de elementos do vetor representa o tamanho da entrada.


O programa contm um comando de iterao (8) que contm um comando
de desio que, por sua vez, contm apenas um comando de atribuio (9).
O comando de atribuio requer tempo constante O(1) para ser executado,
assim como a avaliao do comando de desio. Considerando o pior caso, o
comando de atribuio sempre ser executado.
O tempo para incrementar o ndice do lao e avaliar sua condio de
terminao tambm O(1), e o tempo combinado para executar uma vez o
lao composto pelas linhas (8) e (9) O(max(1, 1)) = O(1), conforme a regra de
soma para a notao O, e considerando que o nmero de iteraes do lao
n - 1, ento o tempo gasto no lao (8) O((n - 1) x 1) = O(n - 1), conforme a regra
do produto para a notao O.
O algoritmo estruturado com base em um comando de desio, cuja
condio checada em tempo constante, da mesma forma que a edio da
mensagem de erro (O(1)). Por outro lado, utilizando a regra da soma nova-
mente, temos que a execuo das linhas (7), (8) e (9) consome O(max(1, n - 1))
= O(n - 1). No pior caso temos que a execuo do bloco (5) consome O(n - 1).
Finalmente, o comando (11) executado em tempo O(1). Aplicando novamente
a regra da soma entre (5) e (11) temos que O(max(n 1, 1)) = O(n - 1). Portanto
a complexidade temporal do algoritmo Maximo linear.

Simplifi cando a anlise, a quantidade de trabalho do algoritmo pode


ser determinada pela quantidade de execues da operao fundamental. No
entanto, pode existir mais de uma operao fundamental com pesos diferen-
tes. Neste caso, a regra de soma para a notao O pode ser aplicada.

20 ESTRUTURA DE DADOS
Considere o algoritmo buscaBinaria descrito a seguir:
int buscaBinaria (int array[], int chave, int n){
int inf = 0; //Limite inferior
int sup = n - 1; //Limite superior
int meio;
while (inf <= sup) {
meio = (inf + sup) / 2;
if (chave == array[meio])
return meio;
else if (chave < array[meio])
sup = meio - 1;
else inf = meio + 1;
}
return -1; // no encontrado
}
1. Descreva o funcionamento do algoritmo buscaBinaria. Qual situao
representa o pior caso? e o melhor?
2. Considerando a execuo do algoritmo buscaBinaria em um vetor com
15 elementos, quantas repeties (nmero de passos) so necessrios
para o algoritmo detectar que uma determinada chave de busca no se
encontra no vetor.
3. Determine a complexidade temporal do algoritmo buscaBinaria anali-
sando passo-a-passo a complexidade de cada comando.

Nesta unidade foi apresentado um estudo introdutrio sobre os fun-


damentos da teoria sobre complexidade de algoritmos. Esta teoria de
fundamental importncia uma vez que possibilita determinar a melhor
soluo para um determinado tipo de problema, assim como tambm ela-
borar projetos de algoritmos cada vez mais efi cientes.

ESTRUTURA DE DADOS 21
CORMEN T. H., LEISERSON C. E., RIVEST R. L., STEIN C. (2001). Intro-
duction to Algorithms. McGraw-Hill e The Mit Press.
KNUTH D. E. (1968). The Art of Computer Programming, Vol. 1: Funda-
mental Algorithms. Addison-Wesley.
KNUTH D. E. (1971). Mathematical Analysis of Algorithms. Procedings
IFIP Congress 71, vol. 1, North Holland, 135-143.
WIRTH N. (1986). Algorithms and Data Strutures. Prentice-Hall.
ZIVIANI N. (2005). Projeto de Algoritmos com implementaes em Pas-
cal e C, 2da. Edio. Thomson.

22 ESTRUTURA DE DADOS
Unidade

2
Representao dos Dados

Objetivos:
Nesta unidade descrito o processo de abstrao seguido para a modelagem e
desenvolvimento de uma soluo computacional a partir de um problema do mundo
real. Neste contexto, os conceitos de tipos de dados, estruturas e tipos abstratos
so introduzidos, ressaltando sua importncia para a adequada modelagem,
manipulao e representao na memria do computador.
Captulo 1
Modelagem Conceitual

Para que um problema do mundo real possa ser resolvido compu-


tacionalmente necessrio utilizar mtodos e tcnicas que possibilitem a
modelagem adequada do problema, de forma que possa ser interpretado e
processado pelo computador para gerar uma soluo.
Os modelos so utilizados para representar o mundo real de forma
simplifi cada, com o objetivo de facilitar o gerenciamento da complexidade.
Um modelo refl ete os aspectos considerados importantes para o desenvolvi-
mento da aplicao, deixando em um segundo plano, os aspectos que no
so relevantes.
A modelagem de situaes do mundo real alcanada atravs de um
processo de abstrao, a partir do qual, somente as propriedades relevantes
para a aplicao so consideradas no modelo.

Bit signifi ca dgito binrio,


do ingles BInary digiT. Um
bit a menor unidade de
informao que pode ser
armazenada ou transmiti-
da. Um bit pode assumir
O processo de abstrao envolve a observao das entidades presentes somente 2 valores: 0 ou 1,
verdadeiro ou falso.
no domnio do problema para a correspondente representao no domnio O conjunto de 8 bits de-
computacional. nominado de Byte.
No nvel mais baixo de abstrao, a representao dos dados a nvel
de mquina acontece de acordo a padres de bits e bytes de memria.
No entanto, as linguagens de programao modernas possibilitam que o
programador possa trabalhar com objetos relativamente complexos em um
nvel mais alto de abstrao, tornando transparente ao desenvolvedor a ma-
nipulao dos dados ao nvel da sua representao interna no computador.
Esta facilidade alcanada atravs da utilizao de uma variedade de tipos
de dados.

Tipo de dados
O tipo de dados associado a uma varivel, numa linguagem de progra-
mao, defi ne o conjunto de valores que a varivel pode assumir. Isto , a O sistema operacional
(SO) um programa ou
declarao da varivel como sendo de um tipo especfi co determina: conjunto de programas
1. A quantidade de bits que devem ser reservados na memria. responsvel por gerenciar
todos os recursos do sis-
2. Como o dado representado por esse padro de bits deve ser inter- tema, tais como: coman-
dos do usurio, arquivos,
pretado (p.e., uma cadeia de bits pode ser interpretada como sendo
memria, etc.
um inteiro ou real).

ESTRUTURA DE DADOS 25
Os tipos tm geralmente associaes com valores na memria ou va-
riveis. Consequentemente, tipos de dados podem ser vistos como mtodos
para interpretar o contedo da memria do computador, o que pode variar
conforme o sistema operacional e a linguagem de implementao.

Na sua maioria, as linguagens de programao exigem que um co-


mando declarativo que defi ne uma varivel especifi que tambm o tipo de
dados associado varivel. Estas linguagens so chamadas de fortemen-
te tipadas. Em contrapartida, as linguagens fracamente tipadas permitem
que a defi nio do tipo correspondente a uma varivel possa ser determina-
da dinamicamente, em tempo de execuo.

Os tipos de dados podem ser classifi cados em dois grupos: primitivos


ou bsicos e compostos ou estruturados.
Os tipos de dados primitivos so fornecidos pela linguagem de progra-
mao como um bloco de construo bsico. Dependendo da implementa-
A memria o dispositivo o da linguagem, os tipos primitivos podem ou no possuir correpondn-
que permite a um compu-
tador armazenar dados de cia direta com objetos na memria. Exemplos de tipos primitivos comuns
forma temporria ou per- so: inteiro, real, caractere, booleano, dentre outros.
manente.
Alm de estabelecer um esquema predeterminado de armazenamento,
a defi nio de um tipo de dados primitivo estabelece tambm um conjunto
de operaes predefi nidas sobre aquele tipo. Consequentemente, a defi nio
de uma varivel como instncia de um desses tipos determina o conjun-
to de operaes que podem ser realizadas utilizando essas variveis. Por
exemplo, ao considerar variveis do tipo primitivo inteiro (int), as operaes
permitidas se traduzem nos operadores aritmticos vlidos para os valores
desse tipo, no caso: soma (+), subtrao (-), multiplicao (*), diviso inteira
(DIV) e resto da diviso inteira (MOD). Estas operaes so implementadas
de forma nativa por qualquer linguagem de programao, e seu desenvolvi-
mento fi ca transparente ao usurio.
Dada a complexidade das entidades do domnio do problema a serem
O fosso semntico repre-
modeladas e representadas no universo computacional, o fosso semntico
senta a diferena entre (gap semntico) envolvendo a descrio de alto nvel de uma entidade (do-
uma descrio de alto n- mnio do problema), e a descrio de baixo nvel (domnio da soluo) pode
vel e outra de baixo nvel ser inconcilivel. Neste contexto, a possibilidade de defi nir tipos de dados
relativa a uma mesma en-
tidade. que possibilitem a representao destas entidades de forma mais prxima
da realidade facilita o processo de abstrao, assim como contribui para a
reduo do fosso semntico entre ambos os domnios.
O programador pode defi nir tipos de dados prprios que mais corres-
pondam s necessidades de suas aplicaes. Linguagens de programao
atuais permitem aos programadores defi nir tipos de dados adicionais, uti-
lizando os tipos primitivos e as estruturas como blocos construtivos. Por
exemplo, para defi nir a varivel Empregado com esta estrutura heterognea
em C seria:

struct{
char Nome[9]
int Idade
fl oat Qualificao
} Empregado

No entanto, se a estrutura for muito frequente, o programa pode fi car


volumoso e difcil de ser lido. O mtodo mais adequado consiste em descre-

26 ESTRUTURA DE DADOS
ver a estrutura de dados correspondente uma nica vez, associando-a a um
nome descritivo, e utilizar esse nome todas as vezes que for necessrio.

typedef struct {
char Nome[9]
int Idade
float Qualificao
} TipoEmpregado

Esta declarao define um novo tipo denominado TipoEmpregado que


pode ser usado para declarar variveis da mesma forma como um tipo pri-
mitivo.
TipoEmpregado Empregado

A partir desta definio possvel gerar as correspondentes variveis


instncia, as quais iro assumir valores nos atributos, dependendo do tipo.
Por exemplo, valores vlidos para uma varivel do tipo Empregado podem ser:

Nome: Joo Soares


Idade: 25 anos
Qualificao: 8.58

Um tipo definido pelo usurio essencialmente um modelo usado para


construir instncias de um dado tipo, que descreve todas as caractersticas
que todas as instncias deste tipo devem assumir mas no constitui, ele
prprio, uma ocorrncia real deste tipo.
A forma conceitual dos dados materializada pela estrutura de dados
utilizada na implementao do tipo. Uma estrutura de dados uma forma
particular de se implementar um tipo, e construda dos tipos primitivos
e/ou compostos de uma linguagem de programao, e por este motivo so
chamados de tipos compostos ou estruturados.
Um tipo composto envolve um conjunto de campos e membros orga-
nizados de forma coerente, onde o tamanho total da estrutura corresponde
soma dos tamanhos dos campos constituintes. Exemplos de tipos estru-
turados so: registros, vetores, matrizes, arquivos, rvores, dentre outros.
A escolha por uma estrutura de dados determinante na qualidade
e esforo requerido para o desenvolvimento da soluo. As estruturas de
dados e algoritmos so escolhidos com base em critrios diversos, tais como
desempenho, restries de plataforma de hardware e software, capacidade
do equipamento, volume de dados, etc. As estruturas de dados dividem-se
em homogneas e heterogneos. As estruturas homogneas so conjuntos
de dados formados por componentes do mesmo tipo de dado (p.e., vetores,
matrizes, pilhas, listas, etc.). Em contrapartida, as estruturas heterogne-
as so conjuntos de dados formados por componentes pertencentes a tipos
de dados diferentes (p.e., registros). A escolha de uma estrutura de dados
apropriada pode tornar um problema complicado em uma soluo bastante
trivial.
Diferentemente do que acontece na definio de tipos de dados bsi-
cos, onde um conjunto de operaes de manipulao fornecido, no caso
dos tipos estruturados definidos pelo usurio apenas novos esquemas de
armazenamento so definidos. Isto significa que, a principio, no so forne-
cidos meios para definir as operaes a serem executadas sobre instncias

ESTRUTURA DE DADOS 27
de tais estruturas. Consequentemente, algoritmos de manipulao preci-
sam ser desenvolvidos de forma a possibilitar a correta utilizao e acesso
s novas estruturas defi nidas.

1. Defi na os conceitos de tipo de dado bsico e tipo de dado defi nido pelo
usurio.
2. Cite como exemplos tipos de dados bsicos que voc conhece e detalhe
suas caractersticas e as operaes permitidas sobre esses tipos.
3. Defi na um tipo de dado estruturado que descreva de forma adequada e
completa as seguintes informaes:
a. Livro
b. Crculo
c. Filme
d. Pessoa
e. Aluno
O paradigma orientado a
objetos envolve um con- f. Item de estoque
junto de tcnicas, mto-
dos e ferramentas para g. Conta bancaria
anlise, projeto e imple-
mentao de sistemas
de software baseado na
composio e interao de
componentes de software Tipo abstratos de dados
denominados de objetos.
Um tipo de dado definido pelo usurio, incrementado com a defi nio e
implementao das operaes necessrias para a sua manipulao, consti-
tui um Tipo Abstrato de Dados (TAD), conceito central no contexto do Para-
digma Orientado a Objetos. A utilizao de TADs permite que linguagens
de programao de propsito geral sejam personalizadas para um domnio
de aplicao mais especfi co. Uma vez defi nidos, podem ser empregados
como primitivas da linguagem, e possibilitam o desenvolvimento de compo-
nentes de software reusveis e extensveis.
TADs estendem a noo de tipo de dado (estrutura de dados + ope-
raes) com base na utilizao de tcnicas de ocultamento da informao
Uma interface lista os ser-
vios fornecidos por um
referente estrutura de dados utilizada e implementao das operaes
componente, restringindo defi nidas. Este objetivo alcanado atravs de uma clara separao entre
o acesso de entidades ex- interface e implementao.
ternas ao objeto.
A interface lista todos os Na abordagem orientada a objetos (OO), o processo de abstrao utili-
mtodos e argumentos zado para chegar a uma modelagem computacional de entidades do mundo
que o objeto entende e
real baseado na anlise das suas funcionalidades. Desta forma, os obje-
capaz de realizar.
Defi ne a interface de aces- tos so categorizados com base na estrutura e no comportamento comum
so estrutura sem fazer atravs da implementao de classes. Uma classe defi ne um TAD a partir
qualquer referncia im- de trs componentes: defi nio da interface pblica, defi nio da estrutura
plementao utilizada, e
possibilita uma clara se- de dados, e a implementao da interface com base na estrutura de dados
parao entre implemen- escolhida. A interface pblica, uma vez que possibilita o acesso aos da-
tao e especifi cao. dos da classe, enquanto que a implementao privada, ou seja, oculta ao

28 ESTRUTURA DE DADOS
usurio da classe. A seguir apresentada uma ilustrao que descreve a
organizao de um TAD.

A interface do TAD independente da repre-


sentao escolhida para a sua implementao. Isto
signifi ca que a mesma interface pode ser implemen-
tada utilizando diferentes estruturas de dados. A in-
terface propicia uma forma de encapsulamento pro- Uma classe representa
tegendo a informao privada de acessos indevidos. um conjunto de objetos
com caractersticas afi ns.
Adicionalmente, este mecanismo facilita a realizao Uma classe defi ne o com-
de mudanas, uma vez que estas acontecem de for- portamento dos objetos
ma transparente ao resto do programa, sempre que atravs de seus mtodos,
a interface seja mantida. Esta modelagem facilita o e o estado atravs de seus
atributos. Exemplo de
desenvolvimento, extensibilidade e propicia o reuso classe: animais, vegetais,
de software. minerais.

A seguir apresentado como exemplo a defi nio


do tipo abstrato Retngulo. Um retngulo pode ser
defi nido pela sua largura e altura. A especifi cao do
tipo retngulo pode ser defi nida como:

typedef struct {
oat altura, largura;
} TipoRetangulo

A partir destas informaes possvel calcular sua rea e permetro.


Portanto, alm do construtor do tipo e das operaes de consulta sobre as
informaes do retngulo, as operaes de clculo de rea e permetro so
requeridas.
Desta forma, a interface do tipo abstrato retngulo inclui as seguintes
O construtor um mto-
operaes de manipulao. do distinguido que tem
// construtor como funo principal a
de instanciar o objeto cor-
Retangulo (fl oat a, fl oat l); retamente, para seu uso
posterior.
// atribui um valor altura
void InitAltura (fl oat a);

// retorna o valor da altura


fl oat Altura (void) ;

// atribui um valor largura


void InitLargura (fl oat l);
// retorna o valor da largura
fl oat Largura (void);

// calcula o valor do permetro


fl oat Perimetro (void);

// calcula o valor da rea


fl oat Area (void) const;

ESTRUTURA DE DADOS 29
Finalmente, todos os mtodos da interface so implementados na lin-
guagem de programao. Exemplos da implementao de alguns dos mto-
dos da interface so apresentados a seguir.

Retangulo::Retangulo (fl oat a, fl oat l){


altura = a; largura = b;
}

fl oat Retangulo::Altura (void) {


return altura;
}

fl oat Retangulo::Perimetro (void) {


return 2 * (altura + largura);
}

Linguagens orientadas a objetos (OO) fornecem inmeros mecanismos


para dar apoio conceituao envolvida na defi nio e implementao de
TADs. Dentre estes mecanismos temos:
Encapsulamento atravs de qualifi cadores
(private, public e protected).
Herana
Polimorfi smo
Sobrescrita de operaes.
A fase de projeto produz
uma descrio computa-
cional do que o software
deve fazer, e deve ser co-
O projeto de um tipo abstrato uma tarefa difcil, pois este deve ser
erente com as especifi ca- ideado de forma a possibilitar a sua utilizao por parte de terceiros, favo-
es geradas na anlise, recendo o reuso e agilizando o processo de desenvolvimento de software. A
de acordo com os recursos
tecnolgicos existentes.
atividade de projeto envolve a escolha de operaes adequadas, delinean-
do seu comportamento consistentemente, de forma que estas possam ser
combinadas para realizar funes mais complexas, a partir de operaes
simples.
No intuito de aumentar o reuso das operaes, estas devem ser defi ni-
das de forma coesa, e ter um comportamento coerente, com um propsito es-
pecfi co e evitando considerar diversos casos especiais em um mesmo cdigo.
O conjunto de operaes que integram a interface do TAD deve ofere-
cer todas as operaes necessrias para que os usurios possam manipu-
A coeso defi nida como lar a estrutura adequadamente. Um bom teste consiste em checar se todas
a medida de proximidade as propriedades do objeto de um determinado tipo podem ser acessadas.
no relacionamento entre
todas as responsabilida- De forma geral, os tipos abstratos de dados (TADs) so caracterizados
des, os dados e os mto- atravs de suas operaes. No entanto, no cdigo, uma classe que imple-
dos de uma classe. Sim- menta um tipo abstrato possui uma representao: a estrutura de dados
plifi cando, coeso pode
ser traduzida como a me- propriamente dita que suporta tais operaes. A representao envolve uma
dida que indica se uma coleo de campos cada um dos quais associado a um tipo de dados.
classe ou operao tem
uma funo bem defi nida
Em uma representao recursiva, um campo pode ser vinculado a
no sistema. Em geral, a outro tipo abstrato ou uma classe.
alta coeso considera-
da uma propriedade al- A escolha pela representao mais adequada ao problema envolve
tamente positiva por que uma anlise aprofundada, uma vez que cada representao possvel possui
facilita o reuso.
diferentes vantagens e desvantagens.

30 ESTRUTURA DE DADOS
1. Defi na os conceitos de Tipo Abstrato de Dados e de Classe. Estabelea o
relacionamento que vincula ambos conceitos.
2. Defi na TADs para os tipos de dados estruturados para as entidades
listadas a seguir especifi cando detalhadamente a interface completa. A
interface deve incluir todas as operaes necessrias para a correta ma-
nipulao do tipo, dentre elas os mtodos de inicializao, modifi cao,
e consulta.
a. Livro
b. Crculo
c. Filme
d. Pessoa
e. Aluno
f. Item de estoque
g. Conta bancria
3. Implemente duas das interfaces propostas no exerccio anterior utili-
zando a linguagem de programao da sua escolha ou pseudo-cdigo
prximo da linguagem.

Critrios para a escolha da estrutura de dados


adequada
Como dito anteriormente, a interface do TAD independe da implemen-
tao e, portanto, diferentes estruturas de dados podem ser utilizadas como
esquema de armazenamento na memria para seus atributos. A partir do
esquema utilizado os dados podem ser armazenados e recuperados.
A forma em que a alocao de memria acontece, pode ser um fator
determinante para a escolha de uma determinada estrutura de dados.

Uso da memria
A memria o dispositivo
Informalmente, podemos dizer que existem trs maneiras de reservar- que permite a um compu-
tador guardar dados de
mos espao de memria para o armazenamento de informaes: forma temporria ou per-
Uso de variveis globais (e estticas). O espao reservado para uma manente.
varivel global existe enquanto o programa estiver sendo executado.
Uso de variveis locais. Neste caso o espao fi ca reservado apenas
enquanto a funo que declarou a varivel est sendo executada,
sendo liberado para outros usos quando a execuo da funo ter-
mina. Por este motivo, a funo que chama no pode fazer refe-
rncia ao espao local da funo chamada. As variveis globais ou
locais podem ser simples ou vetores, sendo que no caso dos vetores,
preciso informar o nmero mximo de elementos ou tamanho do
vetor. A partir do tamanho informado, o compilador reserva o espa-
o correspondente.

ESTRUTURA DE DADOS 31
Requisies ao sistema em tempo de execuo. Este espao alocado
dinamicamente permanece reservado at que explicitamente seja
liberado pelo programa. Uma vez que o espao liberado fica dispo-
nvel para outros usos. Se o espao alocado no for liberado explici-
tamente pelo programa, este ser automaticamente liberado quando
a sua execuo terminar. A seguir ilustrada esquematicamente a
alocao da memria pelo sistema operacional.
Quando requisitamos ao sistema
operacional para executar um de-
terminado programa, o cdigo em
linguagem de mquina do progra-
ma deve ser carregado na memria.
O sistema operacional reserva tam-
bm o espao necessrio para ar-
mazenarmos as variveis globais (e
estticas) utilizadas ao longo do
programa. O restante da memria
utilizado pelas variveis locais e pe-
las variveis alocadas dinamica-
mente enquanto o programa est
executando.
Cada vez que uma determinada fun-
o chamada, o sistema reserva o
espao necessrio para as variveis
locais da funo. Este espao per-
tence pilha de execuo e, quando
a funo termina, desempilhado e
liberado. A parte da memria no ocupada pela pilha de execuo pode ser
requisitada dinamicamente. Se ao longo de diversas chamadas a funo, a
pilha cresce atingindo o espao disponvel existente, dizemos que ela estou-
rou e o programa abortado com erro. Similarmente, se o espao de mem-
ria livre for menor que o espao requisitado dinamicamente, a alocao no
feita e o programa pode prever um tratamento de erro adequado (por exem-
plo, podemos imprimir a mensagem Memria insuficiente e interromper a
execuo do programa).

Como mencionado anteriormente, a alocao de memria pode acon-


tecer em tempo de compilao (esttica) ou em tempo de execuo (dinmi-
ca). No caso da alocao de memria em forma esttica, o espao destinado
para o armazenamento dos dados possui um tamanho fixo, que no pode
ser modificado ao longo da execuo do programa. Adicionalmente, a aloca-
o de memria acontece em espaos contguos, isto , um do lado do outro.
Exemplos de alocao esttica de memria so variveis globais e vetores.
No caso do vetor, a partir de certo endereo que armazena o primeiro ele-
mento a1 do vetor, os elementos subsequentes podem ser acessados direta-
mente incrementando em k o endereo inicial do vetor, onde k o tamanho
de memria ocupado por cada elemento do vetor.

32 ESTRUTURA DE DADOS
Em contrapartida, no caso de alocao dinmica, a memria ge-
renciada sob demanda, ou seja, os espaos de memria so alocados e de-
salocados dependendo da necessidade, durante a execuo do programa.
Consequentemente, a alocao no acontece necessariamente de forma
contgua (ou sequencial), podendo, os dados, fi carem esparsos na memria
do computador. A partir desta confi gurao onde os dados so armazena-
dos de forma no sequencial, o acesso alcanado atravs de variveis do
tipo ponteiro, indicando o endereo de memria correspondente. A seguir
ilustrada esquematicamente a distribuio dos elementos integrantes de
uma cadeia ao longo da memria. Na primeira coluna indicado o endereo
correspondente ao contedo. A coluna ponteiro indica o endereo do prxi-
mo elemento na cadeia. Note que o segundo elemento no ocupa o endereo
consecutivo ao a1.
Endereo Contedo Ponteiro Observao O ponteiro ou apontador
Primeiro elemento acessado um tipo de dado que ar-
L=3FFB a1 1D34 mazena o endereo de um
a partir de L
outro dado.
1D34 a2 BD2F A partir do ponteiro, o
dado que se encontra no
BD2F a3 AC13 respectivo endereo pode
1500 an-2 16F7 ser acessado e manipu-
lado.
16F7 an-1 5D4A
ltimo elemento da cadeia.
5D4A an null O endereo null indica que o
elemento no tem sucessor.

A partir das caractersticas de cada uma das abordagens para a alo-


cao dos dados, vantagens e desvantagens podem ser estabelecidas.
Alocao esttica:
Vantagem: Possibilita acesso direto ao local da memria, uma vez
que os dados se encontram armazenados de forma contgua ou se-
quencial. Consequentemente, em alguns casos, as operaes de
busca podem ter custo constante O(1).
Desvantagem: preciso determinar em tempo de codifi cao, quan-
to espao necessrio. Esta estimativa pode ser difcil de ser esta-
belecida, e est sujeita a fl utuaes ao longo da execuo. Conse-
quentemente o espao pode resultar insufi ciente ou pode ter sido
sobreestimado. Por outro lado, a alocao sequencial na memria
prejudica as operaes de insero e remoo, uma vez que a se-
quencialidade dos dados precisa ser preservada. Com isso, no pior
caso, o custo destas operaes pode ser de O(n) por conta dos deslo-
camentos necessrios para abrir ou fechar espaos para insero e
remoo, respectivamente.
Alocao dinmica:
Vantagem: no necessrio fi xar o tamanho da estrutura a priori,
uma vez que a alocao de memria feita sob demanda em tempo
de execuo. Com isso evitado o desperdcio de espao, e o risco
de fi car sem espao reduzido. Consequentemente, no existe res-
trio encima do nmero de inseres e remoes. Adicionalmente,
estas operaes no requerem de nenhum esforo adicional uma
vez que envolvem somente o ajuste dos ponteiros j que os elemen-
tos se encontram esparsos na memria.
Desvantagem: o gerenciamento dos dados diretamente da memria
pode ser trabalhoso e propenso a erros. Como conseqncia da

ESTRUTURA DE DADOS 33
no linearidade na alocao dos dados, o acesso a um determina-
do elemento i torna necessrio o percurso pelos i 1 elementos an-
teriores na sequncia. Esta propriedade, que caracteriza o acesso
sequencial aos dados, torna a operao de busca por um elemento
de custo O(n).

Nesta unidade foi apresentado o conceito de abstrao e seus nveis,


e a sua importncia no processo de modelagem. Tipos de dados bsicos e
estruturados foram defi nidos neste contexto, como meios de representar e
interpretar as informaes manipuladas pela aplicao. Adicionalmente, o
conceito de tipo abstrato estabelecido como um mecanismo de extenso
e customizao de linguagens de programao, no intuito de facilitar o de-
senvolvimento de sistemas. TADs so caracterizados por suas operaes,
as quais so encapsuladas junto sua estrutura, sendo acessveis exclu-
sivamente atravs da interface especifi cada, garantindo independncia da
implementao utilizada. A independncia de representao torna possvel
alterar a representao de um tipo sem que seus clientes sejam afetados.
Finalmente, noes de gerncia de memria foram introduzidas, focando
nas principais caractersticas que infl uenciam na escolha pela alocao
esttica ou dinmica da memria. Uma anlise dos fatores que contribuem
na tomada de deciso foi apresentada.

CORMEN T. H., LEISERSON C. E., RIVEST R. L., STEIN C. (2001). Intro-


duction to Algorithms. McGraw-Hill e The Mit Press.
TENENBAUM A. M., LANGSAM Y., AUGENSTEIN M. J. (1995). Estruturas
de Dados Usando C, Makron Books/Pearson Education.
WIRTH N. (1986). Algorithms and Data Structures. Prentice-Hall.
ZIVIANI N. (2005). Projeto de Algoritmos com implementaes em Pas-
cal e C, 2da. Edio. Thomson.

34 ESTRUTURA DE DADOS
Unidade

3
Listas

Objetivos:
Existem certas estruturas clssicas que se comportam como padres uma vez
que so utilizadas na prtica em diversos domnios de aplicao. Nesta unidade
apresentada a estrutura de dados Lista e o correspondente Tipo Abstrato,
detalhando a sua interface e apresentando duas implementaes: vetores e
ponteiros. Variantes do tipo abstrato listas, na forma de Pilhas e Filas, de ampla
utilizao prtica, so descritas.
Captulo 1
Listas

Introduo
Um conjunto de elementos pode ser intuitivamente representado atra-
vs de uma lista linear. Listas so estruturas extremamente fl exveis que
possibilitam uma ampla manipulao das informaes uma vez que inser-
es e remoes podem acontecer em qualquer posio.
Uma lista pode ser defi nida como uma estrutura linear, fi nita cuja or-
dem dada a partir da insero dos seus elementos componentes. As listas
so estruturas compostas, constitudas por dados de forma a preservar a
relao de ordem linear entre eles. Cada elemento na lista pode ser um dado
primitivo ou arbitrariamente complexo.
Em geral, uma lista segue a forma a1, a2, a 3, ..., an, onde n determina o
tamanho da lista. Quando n = 0 a lista chamada nula ou vazia. Para toda
lista, exceto a nula, ai + l segue (ou sucede) ai (i < n), e ai - 1 precede ai (i > 1). O
primeiro elemento da lista a1, e o ltimo an. A posio correspondente ao
elemento ai na lista i.
As caractersticas bsicas da estrutura de dados lista so as seguintes:
Homognea. Todos os elementos da lista so do mesmo tipo. Uma estrutura dita de
linear uma vez que seus
A ordem nos elementos decorrente da sua estrutura linear, no elementos componentes
entanto os elementos no esto ordenados pelo seu contedo, mas se encontram organizados
pela posio ocupada a partir da sua insero. de forma que todos, a ex-
ceo do primeiro e lti-
Para cada elemento existe anterior e seguinte, exceto o primeiro, que mo, possuem um elemen-
no possui anterior, e o ltimo, que no possui seguinte. to anterior e um posterior,
somente.
possvel acessar e consultar qualquer elemento na lista.
possvel inserir e remover elementos em qualquer posio.

Definio do TAD Lista


Como apresentado na unidade anterior, a defi nio de um Tipo Abs-
trato de Dados (TAD) envolve a especifi cao da interface de acesso para
a manipulao adequada da estrutura, a partir da qual so defi nidas em
detalhe, as operaes permitidas e os parmetros requeridos. O conjunto
de operaes depende fortemente das caractersticas de cada aplicao, no
entanto, possvel defi nir um conjunto de operaes mnimo, necessrio e
comum a todas as aplicaes.

ESTRUTURA DE DADOS 37
Interface do TAD Lista

/* Cria uma lista vazia


Lista Criar ()

/*insere numa dada posio na lista.


int Inserir (Lista l, tipo _ base dado, corrente pos)

/* Retorna o elemento de uma dada posio


tipo _ base consultaElemento (Lista l, corrente pos)

/*Remove o elemento de uma determinada posio


int Remover (Lista l, corrente pos)

/* Retorna 1 a lista est vazia, ou 0 em caso contrario.


int Vazia (Lista l)

/* Retorna 1 se a lista est cheia, ou 0 em caso contrario.


int Cheia (Lista l)

/* Retorna a quantidade de elementos na lista.


int Tamanho (Lista l)

/* Retorna o prximo elemento na lista a partir da posio


corrente.
corrente proximoElemento (Lista l, corrente pos)

/*Busca por um determinado elemento e retorna sua posio


corrente, ou -1 caso no seja encontrado.
corrente Busca (Lista l, tipo _ base dado)

Uma vez definida a interface, esta pode ser implementada utilizando


uma representao dos dados adequada. Existindo mais de uma estrutura
adequada, a escolha depende principalmente das necessidades e caracters-
ticas dos dados a serem manipulados pela aplicao.
A seguir, o Tipo Abstrato Lista implementado utilizando duas estru-
turas de dados comumente utilizadas e adequadas s necessidades, cada
uma com vantagens e desvantagens particulares.

Implementao do TAD Lista usando alocao esttica


Na implementao de lista adotando alocao de memria esttica os
elementos componentes so organizados em posies contguas de memria
utilizando arranjos ou vetores.
Vantagens e desvantagens desta estrutura foram discutidas na unida-
de 3. Em particular, a utilizao de vetores se torna adequada no caso em

38 ESTRUTURA DE DADOS
que existe uma clara noo do tamanho da entrada a ser processada, e uma
perspectiva que indica que as aplicaes que iro utilizar o TAD no estaro
executando muitas operaes de insero e remoo que possam vir a alte-
rar signifi cativamente o tamanho preestabelecido. A estruturao da lista
utilizando alocao esttica apresentada grafi camente a seguir. Note que,
a partir do endereo correspondente ao primeiro elemento no vetor (pos), e
conhecendo o tamanho (c) de cada componente na lista, possvel calcular
o endereo na memria de qualquer elemento armazenado no vetor. Isso
garante o acesso direto aos elemento em O(1).

A seguir apresentada a defi nio da estrutura de dados e imple-


mentao das operaes defi nidas na interface utilizando alocao esttica
de memria atravs da defi nio de vetores. Considerando a utilizao de
alocao esttica de memria, o tamanho da estrutura de dados precisa ser
determinado em tempo de compilao.

#defi ne tamanho

Uma lista um tipo de dado que estrutura elementos cujo tipo pode
ser arbitrariamente complexo, envolvendo inclusive, a utilizao de outros
TADs. A defi nio a seguir especifi ca o tipo base dos elementos da lista
como inteiros.

A notao utilizada na im-


typedef int tipo _ base; plementao prxima
linguagem C.

Os elementos da lista so organizados em um vetor, de tamanho pre-


defi nido. Adicionalmente, um atributo contendo a quantidade de elementos
da lista (quant_Elem) includo na estrutura no intuito de tornar mais fcil
e gil o acesso aos elementos e possibilitar o controle do crescimento da
estrutura.

typedef struct {
tipo _ base v[tamanho];
int quant _ Elem;
} no _ Lista;

A informao relativa quantidade de elementos existente na lista


pode ser til em diversas situaes uma vez que, conhecendo a posio na Na linguagem C, a posi-
memria (endereo) do primeiro elemento da lista, possvel calcular o en- o que corresponde ao
dereo do ltimo elemento e, consequentemente, da primeira posio dispo- primeiro elemento do ve-
tor corresponde ao ndice
nvel. Isto possvel por conta da propriedade de armazenamento contguo i = 0. Em outras lingua-
propiciada pela estrutura de dados. gens, como por exemplo
Pascal, o primeiro elemen-
to no vetor se encontra na
posio i=1.

ESTRUTURA DE DADOS 39
Finalmente a lista definida como um ponteiro estrutura de dados
onde os elementos so agregados.

typedef no _ Lista *Lista;

A criao de uma lista inicialmente vazia envolve a definio do pon-


teiro correspondente, apontando a um endereo de memria reservado com
tamanho adequado para o armazenamento da estrutura, em particular, o
primeiro n representando a cabea da lista. O tamanho da lista iniciali-
zado em zero uma vez que inicialmente no contem elementos.

Lista Criar () {
Lista l = (Lista) malloc (sizeof (no _ Lista));
If (l != NULL){
l -> quant _ Elem = 0;
return (l);
}
else printf (No existe memria suficiente);
return;
}

Normalmente, a lista precisa ser percorrida de forma a realizar algum


tipo de processamento sobre os dados que a compem. Consequentemente
se torna necessrio um mecanismo que possibilite checar no momento em
que no seja possvel processar mais nenhum elemento. O mtodo ultimoE-
lemento responsvel por fazer esta checagem.

int ultimoElemento (Lista l, corrente pos) {


if (pos + 1 == l -> tamanho) return (1)
else return (0);
}

A execuo de uma operao de remoo requer a existencia de no


mnimo um elemento na lista. O mtodo Vazia retorna o valor 1 no caso da
lista se encontrar vazia, e 0 em caso contrrio.

int Vazia (Lista l) {


if (l -> quant _ Elem == 0) return (1)
else return (0);
}

Outra operao que pode ser de utilidade a checagem pelo caso em que
a estrutura que armazena a lista possa estar cheia, uma vez que esta situao
pode inviabilizar a insero de um novo elemento. Este mtodo de fundamen-
tal importncia, principalmente no caso de utilizao de alocao de memria
esttica onde a tentativa de insero de um novo elemento pode acarretar o
estouro da memria, fazendo com que o programa termine com erro.

40 ESTRUTURA DE DADOS
int Cheia (Lista l) {
if (l -> quant _ Elem == tamanho) return (1)
else return (0);
}

Adicionalmente, o percurso ao longo dos elementos de uma lista re-


quer de uma operao que possibilite a movimentao ao longo da estrutu-
ra, elemento a elemento. A funo proximoElemento retorna o ndice no vetor
correspondente posio do prximo elemento, se for o ltimo e no tiver
prximo, retorna -1.

corrente proximoElemento (Lista l, corrente pos) {


pos = pos++;
if (validaPos(pos)
return (pos);
return (-1);
}

A operao de insero possivelmente uma das mais importantes,


uma vez que atravs dela que a lista ser construda. Em particular, o tipo
lista no possui nenhuma restrio em relao insero, podendo aconte-
cer em qualquer posio. Desta forma, na hora de inserir um elemento na
lista, necessrio informar qual a posio correspondente ao novo elemen-
to, seja no inicio, meio ou fim da lista. Considerando que a insero nem
sempre possvel por conta da limitao de espao da estrutura de dados
utilizada, a funo retorna 1 se a insero foi realizada com sucesso e 0 em
caso contrrio

int Inserir (Lista l, tipo _ base dado, corrente pos) {


int i;
if (!validaPos(l) || (cheia (l))) return (0);

for (i = tamanho(l) ; i >= pos; i--)


l -> v[i] = l -> v[i-1];
l -> v[pos] = dado;
l -> tamanho = (l -> tamanho)++;
return (1);
}

Dependendo da posio onde o elemento ser inserido, o trabalho re-


querido pode ser estimado de forma a estabelecer o custo da funo. Pelo
fato de se utilizar alocao esttica e contgua de memria para o armaze-
namento dos elementos da lista, a insero de um elemento em uma execu-
o requer que o espao fsico na memria seja providenciado em tempo de
compilao. Para isso necessrio deslocar (shift) todos os elementos neces-
srios, desde a posio requerida at o final da lista. Por exemplo, se a lista
possui 5 elementos e o novo elemento precisa ser inserido na posio 3, os
ltimos 3 elementos precisaro ser deslocados direita, para que a posio

ESTRUTURA DE DADOS 41
de insero requerida fique disponvel para o novo elemento a ser inserido.
A situao ilustrada na figura a seguir.

O pior cenrio neste caso acontece quando requerida a insero na


primeira posio da lista, obrigando o deslocamento de todos os elementos
da lista em uma posio direita. Nete caso, o custo requerido O(n).
Analogamente operao de insero, a operao de remoo exclui
um elemento em qualquer posio, portanto esta posio precisa ser infor-
mada explicitamente. O algoritmo responsvel por checar se a posio
informada representa uma posio vlida dentro da estrutura.

int Remover (Lista l, corrente pos) {


int i;
if (vazia(l) || (!validaPos(l)) return (0);

dado = l -> v[pos];


for (i = pos; i <=(tamanho(l))-1; i++)
l -> v[i-1] = l -> v[i];
l -> tamanho = (l -> tamanho)--;
return (1);
}

Realizando uma anlise anloga ao caso da insero, o custo para a


remoo O(n).
No caso em que seja necessrio remover um elemento de acordo com
algum contedo especfico, o elemento em questo precisa ser previamente
localizado atravs da operao de Busca. A partir da posio retornada pela
busca, caso o elemento seja efetivamente encontrado na estrutura, a remo-
o poder ser efetivamente realizada.
A busca por um determinado elemento pode ser originada de duas for-
mas. Na primeira variante, a busca pode ser orientada por um determinado
contedo, retornando como resultado a sua posio na lista, no caso em que
o elemento for efetivamente encontrado, caso contrrio retorna -1.

corrente Busca (Lista l, tipo _ base dado) {


int i;
for (i = 0; i <= tamanho(l); i++)
if (l -> v[i] == dado) return (i);
return (-1);
}

42 ESTRUTURA DE DADOS
O pior caso possvel para esta busca, consiste na situao onde o
elemento procurado no se encontra na lista. Nesta situao a lista ser
percorrida na totalidade, sem sucesso, passando pelos n elementos que de-
terminam seu tamanho. Consequentemente, o custo desta operao no seu
pior caso O(n), ou seja linear.

Na segunda variante, a busca pode acontecer a partir de uma deter-


minada posio na lista, retornando o elemento contido nessa posio.

tipo _ base Consulta (Lista l, corrente pos) {


return (l -> v[pos-1]);
}

A complexidade da busca neste caso O(1) uma vez que consiste no


acesso direto posio correspondente, demandando para isso tempo cons-
tante.

1. Considerando a implementao do TAD utilizando alocao esttica de


memria resolva as questes a seguir:
a) Explique por que o custo da remoo em uma lista implementada uti-
lizando alocao esttica e contgua de memria O(n).
b) Implemente a operao que retorna a quantidade de elementos na lis-
ta, cujo cabealho : int tamanho (lista l). Determine a complexidade
da operao implementada.
c) Implemente o mtodo auxiliar que verifi que se uma determinada po-
sio vlida, isto , se encontra dentro dos limites do vetor. O cabe-
alho da operao int validaPos (corrente pos).

Implementao do TAD Lista usando alocao dinmica


Na implementao do Tipo Abstrato lista adotando alocao de mem-
ria dinmica a alocao de memria gerenciada sob demanda em tempo
de execuo. Esta caracterstica determina que os elementos componentes
so organizados em posies no-contguas, fi cando espalhados ao longo
da memria. Consequentemente, no preciso estimar a priori o tamanho
da estrutura uma vez que o espao alocado na medida da necessidade,
dependendo das operaes de insero e remoo realizadas.
Vantagens e desvantagens desta estrutura foram discutidas na Unida-
de 3. Em particular, esta estrutura se torna adequada quando o tamanho
da estrutura desconhecido e pode variar de forma imprevisvel. No entan-
to, a gerncia da memria torna a implementao mais trabalhosa e pro-
pensa a erros, podendo acarretar em perda de informao. Adicionalmente,
o acesso aos dados seqencial, no sentido que para acessar o elemento na

ESTRUTURA DE DADOS 43
posio m, se torna necessrio percorrer os m - 1 elementos anteriores. Com
isso, no pior caso, a busca por um elemento na lista demanda custo O(n).
A seguir apresentada a defi nio da estrutura de dados e imple-
mentao das operaes defi nidas na interface para o TAD Lista utilizando
alocao dinmica de memria atravs de ponteiros. A notao utilizada na
implementao prxima linguagem C. Esta estrutura representa uma
seqncia de elementos encadeados por ponteiros, ou seja, cada elemento
deve conter, alm do dado propriamente dito, uma referncia para o prximo
elemento da lista. Grafi camente, a estrutura de dados para a implementa-
o de listas utilizando ponteiros a seguinte:

Por exemplo, uma lista com valores de ponteiros a endereos reais tem
a seguinte forma:

O espao total de memria gasto pela estrutura proporcional ao n-


mero de elementos nela armazenados: para cada novo elemento inserido na
estrutura alocado um espao de memria para armazen-lo. Consequen-
temente, no possvel garantir que os elementos armazenados na lista
ocuparo um espao de memria contguo, e, portanto no possvel ter
acesso direto aos elementos da lista. Isto implica que, para percorrer todos
os elementos da lista, devemos explicitamente seguir o encadeamento dos
elementos. Para isto, preciso defi nir a estrutura do n, como uma estrutu-
ra auto-referenciada contendo, alm do contedo de informao, um pontei-
ro ao prximo elemento na sequncia. As defi nies a seguir implementam
a estrutura correspondente.

typedef struct node *no _ ptr;

struct node {
tipo _ base elemento;
no _ ptr prox;
};

Finalmente a lista defi nida como um ponteiro ao primeiro n da lis-


ta, a partir do qual a sequncia de ns encadeada.

typedef apontador _ no Lista;

A implementao de listas com ponteiros requer um cuidado especial


uma vez que qualquer erro na manipulao dos ponteiros pode acarretar
em perda parcial ou total da lista de elementos. Assim sendo, a utilizao

44 ESTRUTURA DE DADOS
de um ponteiro auxiliar para o percurso ao longo da lista pode ser de gran-
de utilidade. Com esse objetivo definimos um tipo Corrente, a ser utilizado
como cpia da lista de forma a possibilitar a sua manipulao com segu-
rana.

typedef no _ ptr Corrente;

A funo que cria uma lista vazia utilizando alocao dinmica de


memria apresentada a seguir. A funo tem como valor de retorno a lista
vazia inicializada, isto , o valor de retorno NULL, pois no existem ele-
mentos na lista.

Lista Criar (){


return (NULL);
}

O mtodo Inicializar posiciona o ndice da posio corrente no inicio


da lista. Desta forma o ponteiro pos aponta para o mesmo local onde se
encontra o primeiro elemento da lista. Este mtodo til quando a lista
precisa ser percorrida desde o inicio.

corrente Inicializar (Lista L){


corrente pos = L;
return (pos);
}

O deslocamento de um elemento para o seguinte na lista dado pelo


percurso ao longo dos ponteiros, onde, a partir do n atual, a funo a se-
guir retorna o ponteiro onde se localiza o prximo elemento na lista.

corrente proximoElemento (corrente p) {


return (p -> prox);
}

A procura por um contedo na lista realizada atravs da funo


Busca. Esta funo percorre a lista desde o inicio, enquanto o elemento no
for encontrado. A funo retorna a posio do elemento na lista em caso de
sucesso na procura, ou NULL se o elemento no for encontrado.

corrente Busca (Lista L, tipo _ base x) {


corrente p = L;
while ((p != NULL) && (p -> elemento != x))
p = p -> prox;
return p;
}

ESTRUTURA DE DADOS 45
O acesso s informaes contidas nos ns da lista realizado atravs
da funo Consulta, que retorna o contedo de informao armazenado no
n referenciado pelo ponteiro corrente.

tipo _ base Consulta (Lista L, corrente p){


if (p != NULL) return (p -> elemento);
}

A remoo de um elemento da lista envolve a anlise de duas situa-


es: a remoo do primeiro n da lista ou de um n em outra posio qual-
quer, sem ser no inicio da lista. A seguir, o processo de remoo em cada
caso ilustrado.
No caso da remoo do primeiro elemento da lista necessrio que o
ponteiro lista seja atualizado, indicando o novo primeiro elemento.

No caso de remoo de um elemento, sem ser o primeiro, o processo


consiste em fazer um by pass sobre esse elemento atravs do ajuste correto
dos ponteiros, para posteriormente liberar a memria correspondente. Para
efetivar a remoo preciso o n anterior ao n a ser removido, que pode ser
obtido a partir da funo auxiliar Anterior.

A funo Remover apresentada a seguir, remove o elemento corres-


pondente a uma determinada posio pos, passada por parmetro. Esta
posio pode ser resultado de um processo de busca, a partir de um deter-
minado contedo. Em ambos os casos preciso liberar a memria corres-
pondente ao n removido.
A seguir apresentado o algoritmo que implementa o processo de re-
moo.

int Remover (Lista l, corrente pos){


corrente noAnterior = Anterior (L, pos);
if (noAnterior == NULL) l = l -> prox;
else {
corrente tmp _ cell = pos;
noAnterior -> proximo = pos -> prox;
free (tmp _ cell);
}
return (1);
}

46 ESTRUTURA DE DADOS
A insero em uma lista pode acontecer em qualquer posio, que
pode ser no inicio, no fi nal ou qualquer outra posio no meio da lista. O
contedo do parmetro pos representa a posio de insero requerida para
o elemento novo a ser inserido, no caso de insero na cabea da lista pos
null. Neste caso, o ponteiro L que apontava ao primeiro elemento da lista
aponta agora para o novo elemento inserido.

Para qualquer outro valor de pos, o processo de insero acontece


como ilustrado a seguir. A lista precisa ser percorrida at a posio de in-
sero requerida. Nesse ponto, o novo elemento ser inserido atualizando os
ponteiros correspondentes.

int Inserir (Lista l, tipo _ base dado, corrente pos){


int i;
Corrente atual = Inicializar (l);
Lista novo = (Lista) malloc(sizeof(struct node));
novo -> elemento = dado;
if (pos == NULL){
novo -> prox = l;
l = novo;
}
else {
while (atual -> next != NULL) and (atual ->
next != pos)
atual = atual -> prox;
novo -> prox = atual -> prox;
atual -> prox = novo;
}
else return (1);
}

A funo Vazia utilizada para verifi car se a lista possui ou no ele-


mentos armazenados. A verifi cao consiste em checar se o ponteiro ao
primeiro elemento null.

ESTRUTURA DE DADOS 47
int Vazia (Lista L) {
if (L == NULL) return (1)
else return (0);
}

A funo ultimoElemento utilizada para verifi car o fi nal da lista. Esta


checagem consiste em determinar se o prximo elemento que segue ao atual
NULL.

int ultimoElemento (corrente p) {


if (p -> prox == NULL) return (1)
return (0);
}

Com exceo de Busca e Anterior todas as operaes consomem tempo


O(1). Isto por que somente um nmero fi xo de instrues executado sem
levar em conta o tamanho da lista. Para Busca e Anterior o custo O(n), pois
a lista inteira pode precisar ser percorrida se o elemento no se encontra ou
for o ltimo da lista.

Utilizando o TAD Lista defi nido nesta unidade, implemente como apli-
cao um programa que, dadas duas listas A e B, crie uma terceira lista L
intercalando os elementos das duas listas A e B.

Lista Intercala (Lista A , Lista B) {


Lista L = cria ();
corrente pos _ L = Inicializar (L);
corrente pos _ A = Inicializar (A);
corrente pos _ B = Inicializar (B);

/*Assumimos que A e A tem o mesmo tamanho


while (not ultimoElemento(pos _ A)) &&
(not ultimoElemento (pos _ B)){
Inserir (L, Consulta (pos _ A), null);
pos _ A = proximoElemento (pos _ A);
Inserir (L, Consulta (pos _ B), null);
pos _ B = proximoElemento (pos _ B);
}
return(L);
}

48 ESTRUTURA DE DADOS
Considerando a implementao do TAD utilizando alocao dinmica de
memria resolva as questes a seguir:
1. Implemente a operao que retorna a quantidade de elementos na lista,
cujo cabealho : int Tamanho (Lista l). Determine a complexidade da
operao implementada.
2. Implemente uma rotina para a remoo de uma lista desalocando a me-
mria utilizada. O cabealho da rotina void Remove_list (Lista L).
3. Implemente a rotina auxiliar chamada anterior usada na remoo, de
acordo com o seguinte cabealho corrente anterior (Lista L, corrente
pos). Esta rotina retorna a posio do elemento anterior a uma outra
posio pos. Se o elemento no for encontrado retorna NULL.
4. Utilizando as operaes defi nidas na interface do TAD Lista implemente
um mtodo que dadas duas listas L1 e L2, calcule L1 L2 (unio) e L1
L2 (interseo). O resultado das operaes deve ser retornado em uma
terceira lista L3.
5. Utilizando as operaes defi nidas na interface do TAD Lista implemente
um mtodo que dada uma lista retorne uma segunda lista onde os ele-
mentos pertencentes primeira estejam ordenados em forma crescente.
Determine a complexidade do seu algoritmo.
6. Escreva um programa que, utilizando o TAD Lista, faa o seguinte:
a) Crie quatro listas (L1, L2, L3 e L4);
b) Insira sequencialmente, na lista L1, 10 nmeros inteiros obtidos de
forma randmica (entre 0 e 99);
c) Idem para a lista L2;
d) Concatene as listas L1 e L2, armazenando o resultado na lista L3;
e) Armazene na lista L4 os elementos da lista L3 (na ordem inversa);
f) Exiba o contedo das listas L1, L2, L3 e L4.

Variaes sobre o TAD Lista


Lista ordenada
Uma lista ordenada uma lista onde seus elementos componentes so
organizados de acordo a um critrio de ordenao com base em um campo
chave. A ordem estabelecida determina que a insero de um determinado
elemento na lista ir a acontecer no lugar correto. A lista pode ser ordenada
de forma crescente ou decrescente.

ESTRUTURA DE DADOS 49
A partir da existncia de um critrio de ordenao na lista, a funo res-
ponsvel pela busca por um determinado contedo na lista pode ser adaptado
de forma a tornar a busca mais eficiente.

Lista circular
A conveno consiste em manter a ltima clula apontando para a pri-
meira. Desta forma, o teste por fim de lista nunca satisfeito. Com isso, pre-
cisa ser estabelecido um critrio de parada de forma a evitar que o percurso
na lista no encontre nunca o fim. Uma forma padro estabelecido com base
no nmero de elementos existentes na lista.

Lista duplamente encadeada


Em alguns casos pode ser conveniente o percurso da lista de trs para
frente atravs da adio de um atributo extra na estrutura de dados, contendo
um ponteiro para a clula anterior. Esta mudana na estrutura fsica acarreta
um custo extra no espao requerido e tambm aumenta o trabalho requerido
nas inseres e remoes, uma vez que existem mais ponteiros a serem ajus-
tados. Por outro lado simplifica a remoo, pois no mais precisamos procurar
a clula anterior (O(n)), uma vez que esta pode ser acessada diretamente
atravs do ponteiro correspondente.

50 ESTRUTURA DE DADOS
Captulo 2
Pilhas

Em geral, as operaes de insero e remoo realizadas sobre lis-


tas so custosas. No caso da implementao utilizando alocao de mem-
ria esttica, estas operaes acarretam a movimentao dos elementos. No
caso da alocao dinmica o deslocamento at a posio correta de insero
ou remoo envolve o percurso ao longo do encadeamento pelos elemen-
tos. Em ambos os casos, o custo destas operaes O(n). Estas situaes
desfavorveis podem ser contornadas se os elementos a serem inseridos e
removidos se encontram em posies determinadas especialmente, como a
primeira ou ltima posio.
Uma Pilha uma lista com a restrio de que inseres e remoes
so executadas exclusivamente em uma posio, referenciada como fim ou
topo.
Pilhas so conhecidas como estruturas LIFO do ingls Last In First
Out ou ltimo que entra primeiro que sai. Em uma Pilha o nico elemento
acessvel o elemento que se encontra no topo. Consequentemente, a ope-
rao de busca ao longo da estrutura, por exemplo, no uma operao
aplicvel para esta estrutura de dados. Graficamente, uma pilha pode ser
representada da seguinte forma:

O funcionamento de uma pilha pode ser facilmente interpretado a


partir de uma analogia simples com uma pilha de livros pesados. Livros
so empilhados, um encima de outro, sendo que o ltimo livro empilhado
o que fica no topo da pilha, e, portanto o nico visvel e que pode ser con-
sultado sem precisar movimentar outros exemplares. Por se tratar de livros
pesados, o acesso a um livro determinado na pilha, requer que os livros
encima deste sejam retirados, um a um, a partir do topo. Desta forma, o
ltimo livro empilhado ser o primeiro a ser retirado da pilha. A partir des-
ta descrio, o funcionamento da pilha pode ser modelado de acordo com a
seguinte interface.

ESTRUTURA DE DADOS 51
Interface do TAD Pilha

/* Cria uma pilha vazia


Pilha Criar ()

/*insere um novo elemento no topo da pilha.


int Push (Pilha p, tipo _ base dado)

/* consulta pelo elemento que se encontra no topo


tipo _ base Top (Pilha p)

/*Remove e retorna o elemento do topo


int Pop (Pilha p)

/* Retorna 1 se no tem mais elementos na pilha, ou 0 em


caso contrario.
int Vazia (Pilha p)

/* Retorna 1 se a pilha estiver cheia, e 0 em caso contra-


rio.
int Cheia (Pilha p)

/* Retorna a quantidade de elementos na pilha.


int Tamanho (Pilha l)
O fato de mquinas mo-
dernas possurem opera-
es sobre pilhas como
parte do conjunto de ins- Pilhas so listas, portanto as abordagens de implementao utiliza-
trues, faz desta estru- das para listas so vlidas para o caso da implementao de pilhas. Consi-
tura uma abstrao fun- derando que a implementao de pilhas representa uma variao de listas,
damental na Cincia da
Computao, depois do
boa parte da especifi cao e implementao de listas pode ser aproveitada.
vetor.

Implementaes do TAD Pilha usando vetores


Levando em conta as restries inerentes prpria estrutura de da-
dos e as restries na manipulao da pilha, a estrutura projetada para
a implementao de listas modifi cada, adicionando mais um campo de
informao referente localizao do elemento que se encontra no topo da
pilha. Esta informao indispensvel na implementao das operaes de
insero e remoo, de forma a possibilitar o acesso direto ao local. Com
essa pequena alterao na estrutura de dados as operaes passam a de-
mandar tempo constante.

52 ESTRUTURA DE DADOS
#define tamanho;

struct estrutura _ Pilha {


int topo;
tipo _ base elementos [tamanho];
};

typedef struct estrutura _ Pilha *Pilha;

Em C uma pilha definida como um ponteiro estrutura, que pas-


sado por valor para as funes que iro modificar o contedo da pilha.
Dada a semelhana com a estrutura de dados utilizada para o caso
de listas, o mtodo Criar se mantem essencialmente o mesmo, adicionando
somente a sentena de inicializao do campo topo para a primeira posio.
Na escolha pela extremidade do vetor a ser definida como o topo onde
a insero e remoo de elementos estar acontecendo, importante ana-
lisar os custos decorrentes desta escolha. Como discutido anteriormente, a
propriedade de alocao contgua de memria traz como desvantagem a ne-
cessidade de movimentaes dos elementos ao longo da estrutura de dados.
Nesse caso, se o topo for escolhido como a primeira posio do vetor, o custo
da insero e remoo seria de O(n). Em contrapartida, a definio de topo
como sendo o ltimo elemento inserido mais conveniente uma vez que este
pode ser acessado em tempo constante a partir do tamanho da estrutura.
A operao de remoo do elemento que se encontra no topo da pilha
descrita no algoritmo a seguir.

tipo _ base Pop (Pilha p) {


tipo _ base v;
v = p -> elementos [p -> topo];
(p -> topo)--;
return v;
}

A remoo de um elemento somente possvel sempre que a pilha


contiver pelo menos um elemento. Nesse caso o elemento copiado em uma
varivel auxiliar para seu retorno posterior, decrementando em 1, conse-
quentemente, a posio do ltimo elemento. A lgica seguida para a imple-
mentao do algoritmo de consulta do topo, Top, a mesma, com a diferena
de que no preciso alterar a posio do topo uma vez que nenhum elemen-
to removido da pilha.
O algoritmo que verifica se a pilha se encontra vazia ou no basea-
do na informao contida no campo topo. Considerando que o topo indica
indiretamente a quantidade de elementos efetivamente contidos na pilha,
a checagem pela posio onde este elemento se encontra utilizado para
estabelecer se a pilha est vazia. Nesse caso a funo retorna 1.

ESTRUTURA DE DADOS 53
int Vazia (Pilha p) {
if (p -> topo == 0) return (1)
else return (0);
}

Uma estratgia similar pode ser utilizada para estabelecer se a pilha se


encontra cheia, s que neste caso a posio do elemento no topo precisa ser
confrontada contra o tamanho total reservado para a estrutura de dados.

Considerando a implementao do TAD utilizando alocao esttica de me-


moria resolva as questes a seguir:
1. Implemente o algoritmo Push, responsvel pela insero de um novo
elemento no topo da pilha, de acordo seguinte especifi cao: int Push
(Pilha p, tipo _ base dado).
2. Implemente o algoritmo que consulta e retorna o contedo correspon-
dente ao elemento que se encontra no topo, atendendo ao seguinte cabe-
alho: tipo _ base Top (Pilha p).
3. Implemente o algoritmo que verifi ca se a pilha est cheia, atendendo ao
seguinte cabealho: int cheia (Pilha p), retornando 1 em caso afi r-
mativo e 0 em outro caso.
4. Explique por que mais conveniente a defi nio do topo da pilha no fi nal
e no no inicio da estrutura.

Implementao do TAD Pilha usando ponteiros


No caso da implementao de pilhas utilizando alocao dinmica de
memria, a desvantagem do acesso sequencial necessrio para alcanar
qualquer elemento da pilha pode ser contornado efi cientemente, uma vez
que no caso da pilha, as operaes acontecem necessariamente a partir de
um extremo. A escolha pelo extremo da estrutura a ser considerado como
topo ir a determinar o custo envolvido na execuo das operaes: enquan-
to que o acesso ao ltimo elemento da pilha envolve custo O(n), o acesso ao
primeiro elemento constante. Consequentemente, no caso da implemen-
tao da pilha utilizando ponteiros, a defi nio do topo como sendo o inicio
(cabea da lista) da pilha mais vantajoso em termos de desempenho e
complexidade.
A estrutura de dados utilizada na implementao da pilha idntica
quela defi nida no caso de listas, consequentemente, a maior parte das ope-
raes so coincidentes, tais como Criar e Vazia.

54 ESTRUTURA DE DADOS
typedef struct node *no _ ptr;

struct no {
tipo _ base elemento;
no _ ptr prox;
};

typedef no _ ptr Pilha;

A partir da deciso de projeto para o TAD Pilha de considerar o topo


para as operaes de insero (push) e remoo (pop) na cabea da lista
de elementos, cuidados especiais na implementao de tais operaes so
requeridos de forma a evitar perda de informao.
A operao Push, responsvel pela insero de um novo elemento no
topo da pilha, consiste na alocao de memria para o novo elemento. Se a
alocao de memria realizada com sucesso, o novo componente instan-
ciado com a informao correspondente e inserido como primeiro elemento
na lista, atualizando consequentemente a cabea da lista com o endereo do
novo elemento. No caso em que a insero acontea com sucesso o algoritmo
retorna 1, e 0 em caso contrario.

int Push (Pilha p, tipo _ base x) {


no _ ptr novo = (no _ ptr) malloc (sizeof (struct no)); As operaes de alocao
if (no _ tmp == NULL){ e desalocao de mem-
ria, malloc e free, respec-
fatal _ error (Memoria insuciente!!); tivamente, so caras. Este
custo pode ser reduzido
return (0); atravs de um algoritmo
} que implemente a remo-
o lgica de elementos
else { onde, em lugar de desa-
locar a memria, a clula
novo -> elemento = x; correspondente mantida
novo -> prox = p; em uma pilha auxiliar de
forma que quando uma
p = novo; nova clula requerida,
return (1); esta pilha checada pri-
meiro, antes de alocar
} uma nova clula.
}

Considerando a implementao do TAD utilizando alocao dinmica de


memoria resolva as questes a seguir:
1. Implemente o algoritmo Pop, responsvel pela remoo de um elemento
no topo da pilha, de acordo seguinte especifi cao: tipo _ base Pop
(Pilha p)

ESTRUTURA DE DADOS 55
2. Implemente o algoritmo que consulta e retorna o contedo correspon-
dente ao elemento que se encontra no topo, atendendo ao seguinte cabe-
alho: tipo _ base Top (Pilha p).
3. Implemente uma operao que libere a memria alocada pela pilha. De-
termine a complexidade do seu algoritmo.
4. Explique por que mais conveniente a definio do topo da pilha no ini-
cio e no no fim da estrutura, no caso de utilizao de ponteiros.
5. Utilizando as operaes definidas na interface do TAD Lista e do TAD
Pilha, elabore um algoritmo que dada uma lista ordenada, inverta a or-
dem dos elementos na lista, utilizando para isso uma pilha. Determine
a complexidade do seu algoritmo.
6. Utilizando as operaes definidas na interface do TAD Pilha escreva um
algoritmo para ordenar pilhas, sendo que no final do processamento os
elementos da pilha devem estar dispostos em ordem crescente de seus
valores. Determine qual a estrutura auxiliar mais adequada para supor-
tar o processo. Determine a complexidade do seu algoritmo.
7. Utilizando as operaes definidas na interface do TAD Pilha escreva um
algoritmo que fornea o maior, o menor e a mdia aritmtica dos elemen-
tos de uma pilha dada como entrada.

56 ESTRUTURA DE DADOS
Captulo 3
Filas

Assim como pilhas, filas so listas que possuem algumas restries


especficas para a execuo das operaes de insero e remoo. Na fila,
as inseres so realizadas em um extremo, enquanto, que ao remover no
outro. A fila segue o modelo FIFO, do ingls First In First Out, ou seja, que o
primeiro que entra na fila o primeiro em sair.

Interface do TAD Fila

/* Cria uma fila vazia


Fila Criar ()

/*insere um novo elemento no topo da fila.


int Inserir (Fila p, tipo _ base dado)

/* Consulta pelo elemento que se encontra no topo


tipo _ base Top (Fila f)

/*Remove e retorna o elemento do topo


int Remover (Fila f)

/* Retorna 1 se no tem mais elementos na fila, ou 0 em caso


contrario.
int Vazia (Fila f)

/* Retorna 1 se a fila estiver cheia, e 0 em caso contrario.


int Cheia (Fila f)

/* Retorna a quantidade de elementos na fila.


int Tamanho (Fila f)

Implementao do TAD Fila usando vetores


Considerando que a operao de remoo acontece em uma extre-
midade e a insero na outra, interessante manter apontadores indican-
do ambos extremos da estrutura, de forma que o acesso seja direto (O(n)).
Consequentemente, a estrutura de dados fila inclui, alm do vetor que ir
a comportar as informaes correspondentes, os ndices correspondentes
ao inicio e fim da fila, e o tamanho da fila relativo ao nmero de elementos
contidos. A seguinte figura mostra uma fila em algum estado intermedirio.

ESTRUTURA DE DADOS 57
De acordo com esta estratgia e depois da remoo de b e a, e da
insero de f e 1, a situao da fila seria a seguinte:

A insero de um elemento na fila incrementa o tamanho e o ndice


que indica o fim da fila, enquanto que na remoo de um elemento o tama-
nho da fila decrementado e o ndice que indica o inicio incrementado.
Esta estratgia evita a movimentao de elementos sempre que uma inser-
o ou remoo for realizada. Com isso o custo de ambas operaes fica
constante.
Levando em conta as restries inerentes manipulao da fila, a es-
trutura projetada para a sua implementao utilizando alocao de mem-
ria esttica ou vetor precisa ser modificada em relao pilha. Neste caso
preciso indicar mais um campo de informao referente localizao do
elemento que se encontra no inicio da fila. Esta informao indispensvel
na implementao das operaes de insero e remoo, de forma a possi-
bilitar o acesso direto ao local. Com essa pequena alterao na estrutura de
dados as operaes passam a ser executadas em tempo constante.
#define tamanho;

struct estrutura _ Fila {


int ini;
int fim;
int quant _ elementos;
tipo _ base elementos [tamanho];
};

typedef struct estrutura _ Fila *Fila;

No entanto existe um problema potencial uma vez que a fila pode ficar
aparentemente cheia, no entanto vrios elementos podem ter sido removi-
dos, podendo existir na verdade poucos elementos na fila (observe a figura
anterior).
A soluo para contornar este problema implementar o chamado
incremento circular encima do vetor, onde sempre que os ndices de inicio ou
de fim chegam no final do vetor, estes so redefinidos na primeira posio
do vetor. Esta estratgia requer um cuidado especial na hora do percurso
sobre a estrutura, uma vez que o fim do vetor precisa ser determinado logi-

58 ESTRUTURA DE DADOS
camente (p.e., pela quantidade de elementos na fila), e no mais fisicamente
pelo fim da estrutura. A figura a seguir exemplifica o funcionamento da fila
utilizao o vetor circular, onde o contedo c foi removido e adicionado o
contedo m.

A criao de uma fila vazia, similarmente criao de uma lista, en-


volve a alocao de memria para a estrutura de dados respectiva, e a pos-
terior inicializao dos campos envolvidos, no caso os ndices de inicio e
fim, e a quantidade de elementos que precisam ser inicializados em 0.
Considerando a insero de elementos acontecendo no fim e a remo-
o no inicio, o cdigo das respectivas operaes apresentado a seguir. No
caso da insero, e levando em conta que o tamanho da estrutura de dados
esttica foi estabelecida em tempo de compilao, importante verificar
que exista espao disponvel para armazenar um novo elemento. Aps esta
verificao, o novo elemento inserido na primeira posio livre indicada
por fim. Aps isso, tanto fim quando a quantidade de elementos precisam
ser atualizados.

void inserir (Fila f, tipo _ base v) {


if (f -> size == tamanho) {
printf (Fila cheia!);
return;
}
f -> elementos [f -> fim] = v;
f -> fim = incrementar (f -> fim);
f -> size++;
}

A implementao do vetor circular requer que seja realizado um incre-


mento especial onde, a partir de uma posio corrente, o mtodo retorna a
posio seguinte ou, no caso de atingir o final do vetor, a posio corrente
especificada como sendo no inicio da estrutura, no caso 0.

int incrementar (int pos){


if (pos == tamanho - 1) return (0);
else return (i++);
}

ESTRUTURA DE DADOS 59
Considerando a implementao do TAD utilizando alocao esttica de me-
mria resolva as questes a seguir:
1. Implemente os algoritmos Criar, Remover e Vazia, de acordo com os res-
pectivos cabealhos defi nidos na interface do TAD.
2. Explique por que mais conveniente a realizao da operao de inser-
o no fi m e de remoo no inicio. Como seria se fosse ao contrario?
3. Escreva um algoritmo para ordenar fi las, sendo que no fi nal do proces-
samento os elementos da fi la devem estar dispostos em ordem crescente
de seus valores. Determine qual a estrutura auxiliar mais adequada
para suportar o processo. Determine a complexidade do seu algoritmo.

Implementao do TAD Fila usando ponteiros


A implementao de fi las utilizando ponteiros segue a mesma estra-
tgia analisada na seo anterior. Como teremos que inserir e retirar ele-
mentos das extremidades opostas da lista, representando o incio e o fi m da
fi la, preciso utilizar dois ponteiros, ini e fim, que apontam respectivamente
para o primeiro e para o ltimo n da fi la. A partir desta necessidade se faz
indispensvel a implementao da fi la utilizando um n diferenciado, cha-
mado de header ou cabealho, para conter estes ponteiros. Essa situao
ilustrada na fi gura abaixo:

A defi nio da estrutura de dados que implementa a abordagem des-


crita a seguinte:

typedef struct no *no _ ptr;

typedef struct no {
tipo _ base elemento;
no _ ptr prox;
};

60 ESTRUTURA DE DADOS
A estrutura de dados envolve a definio de uma lista de elementos, no
mesmo formato em que foi definida para o caso de listas e pilhas. Adicional-
mente, a estrutura correspondente ao n cabealho precisa ser especificada
uma vez que inclui campos diferenciados.

struct cabealho {
no _ ptr ini;
no _ ptr fim;
};

Finalmente, a fila definida como sendo um ponteiro ao n cabealho.


typedef struct cabealho *Fila;

A partir da interface especificada para o TAD fila, as operaes de


criao e verificao pela fila vazia seguem as mesmas estratgias anterior-
mente descritas.
A deciso de projeto em relao s operaes de insero e remoo
envolve estabelecer em qual extremidade da fila cada uma ser executada.
Em particular, a lgica na implementao da operao de remoo de um
elemento em uma lista implementada com ponteiros, requer a procura pelo
elemento anterior na lista, de forma a atualizar o ponteiro para o prximo
elemento (Ver remoo em listas). O custo desta procura pelo anterior
O(n). Esta situao pode ser evitada se a remoo acontece sempre no inicio
da lista, uma vez que no existe anterior que precise ser atualizado. Esta
constatao determina que a escolha mais conveniente em termos de com-
plexidade que cada novo elemento seja inserido no fim da lista enquanto
que a remoo de um elemento seja realizada no incio.
No caso da operao de insero, onde o elemento inserido no fim da
lista, na situao especfica de insero do primeiro e nico elemento, am-
bos os ponteiros ini e fim precisam ser atualizados apontando para o nico
n inserido na fila. Em qualquer outro caso, somente o ponteiro que indica
o final da fila ser atualizado.

void Inserir (Fila* f, tipo _ base dado) {


no _ ptr novo = (no _ ptr) malloc (sizeof (no));
novo -> elemento = dado;
novo -> prox = NULL;
if (f -> fim != NULL) f -> fim -> prox = novo;
else
f -> ini = novo;
f -> fim = novo;
}

Analogamente, a funo para remover um elemento da fila deve atu-


alizar ambos os ponteiros no caso em que for removido o ltimo e nico
elemento existente, tornando a fila vazia (ini e fim nulos).

ESTRUTURA DE DADOS 61
1. Implemente os algoritmos Criar, Remover e Vazia, de acordo com os res-
pectivos cabealhos defi nidos na interface do TAD Fila utilizando pon-
teiros.
2. Explique por que mais conveniente a realizao da operao de inser-
o no fi m e de remoo no inicio. Como seria se fosse ao contrrio?
3. Utilizando as operaes defi nidas na interface do TAD implemente como
aplicao uma operao que libere a memria alocada pela fi la. Deter-
mine a complexidade do seu algoritmo.
4. Utilizando as operaes defi nidas na interface do TAD Fila, escreva um
algoritmo que fornea o maior, o menor e a mdia aritmtica dos elemen-
tos de uma Fila.
5. Utilizando as operaes defi nidas na interface dos TAD Fila e Pilha es-
crever um algoritmo que leia um nmero indeterminado de valores intei-
ros. Considere que o valor 0 (zero) fi naliza a entrada de dados. Para cada
valor lido, determinar se ele um nmero par ou mpar. Se o nmero for
par, ento inclu-lo na FILA PAR; caso contrrio inclu-lo na FILA M-
PAR. Aps o trmino da entrada de dados, retirar um elemento de cada
fi la alternadamente (iniciando-se pela FILA MPAR) at que ambas as
fi las estejam vazias. Se o elemento retirado de uma das fi las for um va-
lor positivo, ento inclu-lo em uma PILHA; caso contrrio, remover um
elemento da PILHA. Finalmente, escrever o contedo da pilha.

Nesta unidade foi apresentado o tipo abstrato de dados Lista, a partir


da defi nio da sua interface. O tipo abstrato foi implementado de acordo
com duas abordagens tradicionais: vetores e ponteiros, analisando as van-
tagens e desvantagens de cada uma das abordagens de acordo com as ca-
ractersticas das aplicaes e operaes mais frequentes.
Os TADs Pilha e Fila foram descritos e implementados como variantes
do TAD Lista. Estes TADs so amplamente difundidos e de comprovada uti-
lidade na resoluo e modelagem de problemas do mundo real.

CORMEN T. H., LEISERSON C. E., RIVEST R. L., STEIN C. (2001). Intro-


duction to Algorithms. McGraw-Hill e The Mit Press.
KNUTH D. E. (1968). The Art of Computer Programming, Vol. 1: Funda-
mental Algorithms. Addison-Wesley.

62 ESTRUTURA DE DADOS
KNUTH D. E. (1971). Mathematical Analysis of Algorithms. Prociedings
IFIP Congress 71, vol. 1, North Holland, 135-143.
SZWARCFITER J. l., MARKENZON L. (2010). Estruturas de Dados e Seus
Algoritmos. 3. Edio. LTC.
WIRTH N. (1986). Algorithms and Data Strutures. Prentice-Hall.
ZIVIANI N. (2005). Projeto de Algoritmos com implementaes em Pas-
cal e C, 2da. Edio. Thomson.

ESTRUTURA DE DADOS 63
Unidade

4
rvores

Objetivos:
Diversas aplicaes requerem de uma organizao e manipulao de dados mais
complexa daquela propiciada atravs de estruturas lineares, analisadas na unidade
anterior. Uma rvore uma estrutura de dados no linear muito eficiente para
armazenar informao de forma a representar relacionamentos de aninhamento
ou hierarquia entre os elementos envolvidos. Nesta unidade so apresentados os
conceitos iniciais relativos a rvores e a sua representao clssica e implementao
atravs da definio do tipo abstrato correspondente. rvores binrias de busca e
balanceadas (AVL) so introduzidas.
Captulo 1
rvores

Vetores e listas so estruturas de dados chamadas de unidimensio-


nais ou lineares, e portanto, no so adequadas para representarmos dados
que devem ser dispostos de maneira hierrquica. Por exemplo, a estrutura
hierrquica de diretrios (pastas), aninhamento, etc. Estruturas de dados
no lineares, como rvores, so ideais para representar este tipo de relacio-
namento.
A ilustrao a seguir representa esquerda o aninhamento de conjun-
tos e direita a representao hierrquica deste aninhamento utilizando
uma rvore.

Uma rvore composta por um conjunto de ns. Existe um n r, deno-


minado raiz, que contm zero ou mais sub-rvores, cujas razes so ligadas
diretamente a r. Esses ns razes das sub-rvores so ditos filhos do n pai, r.

O nmero de filhos permitido por n e as informaes armazenadas


em cada n diferenciam os diversos tipos de rvores existentes:
rvores binrias, onde cada n tem, no mximo, dois filhos.
rvores genricas, onde o nmero de filhos indefinido.
A forma mais natural para definirmos uma estrutura de rvore
usando recursividade. Uma rvore T um conjunto finito de n ns ou vr-
tices, tais que:

ESTRUTURA DE DADOS 67
Se T um conjunto vazio, ou seja n = 0, a rvore nula, ou vazia, ou
Existe um n especial, r, chamado raiz da rvore;
Os demais ns constituem um conjunto vazio ou so particionados
em conjuntos disjuntos no vazios, as sub-rvores de r;
Cada sub-rvore, por sua vez, tambm uma rvore.
Sejam T uma rvore e v um n, tal que v T, Tv a sub-rvore de T que
tem v como raiz. Defi nem-se as seguintes propriedades:
O grau de sada do no v o nmero de sub-rvores que ele possui.
O grau da rvore T o maior grau dentre os de todos os seus ns.
Os fi lhos de v so as razes das sub-rvores de v.
Um n que no tem descendentes chamado de folha ou terminal.
Uma propriedade fundamental de todas as rvores que s existe um
caminho da raiz para qualquer n. Com isto, podemos defi nir a altura de
uma rvore como sendo o comprimento do caminho mais longo da raiz at
uma das folhas. Assim, a altura de uma rvore com um nico n raiz zero.
Um caminho em T uma sequncia de ns v1, v2, ..., vm, tal que para
cada par (vi, vi+1), vi pai de vi+1. O comprimento do caminho m-1.
O nvel do n v o nmero de ns no caminho da raiz at v. O nvel
do n raiz 0, por defi nio.
A altura de um n v o nmero de ns no maior caminho de v at
um dos seus descendentes. Folhas tm altura 1. A altura da raiz
determina a altura da rvore.

rvore binria
Em uma rvore binria, cada n tem zero, um ou dois fi lhos. De ma-
neira recursiva, podemos defi nir uma rvore binria como sendo:
Uma rvore vazia; ou
Pesquise sobre aplicaes
da estrutura de dados
Um n raiz v tendo duas sub-rvores, identifi cadas como a sub-
rvore. rvore da direita (sad) e a sub-rvore da esquerda (sae) de v.

Pela defi nio, uma sub-rvore de uma rvore binria sempre espe-
cifi cada como sendo a sae ou a sad de uma rvore maior, e qualquer das
duas sub-rvores pode ser vazia.
Uma rvore binria T um conjunto fi nito de n ns ou vrtices, tais que:
Se T um conjunto vazio, ou seja, n=0, a rvore nula ou vazia, ou
Existe um n especial, r, chamado raiz da rvore;
Os demais ns constituem um conjunto vazio ou so particiona-
dos em dois conjuntos disjuntos: sub-rvore esquerda e direita de r,
cujas razes so chamadas de fi lho esquerdo e direito de r;
Cada sub-rvore, por sua vez, tambm uma rvore binria;

68 ESTRUTURA DE DADOS
Uma rvore estritamente binria aquela em que cada n possui zero
ou dois filhos, como representado na figura a seguir.

Uma rvore binria completa aquela cujos ns com sub-rvore va-


zias localizam-se no ltimo ou no penltimo nvel. Um exemplo de rvore
binria completa ilustrado na figura abaixo.

Uma rvore binria cheia aquela cujos ns com sub-rvores vazias


localizam-se todos no ltimo nvel. Logo, ela tambm estritamente binria.

Um exemplo de utilizao de rvores binrias est na avaliao de


expresses. Nessa rvore, os ns folhas representam operandos e os ns
internos operadores binrios. Uma rvore que representa, por exemplo, a
expresso (5 + 9) * (3 - 7) + 7 ilustrada na seguinte figura:

ESTRUTURA DE DADOS 69
Dependendo do percurso da rvore a mesma expresso pode ser re-
presentada em forma expresses infi xas, prefi xas e psfi xas.

1. Pesquise sobre aplicaes da estrutura de dados rvore binria.

70 ESTRUTURA DE DADOS
Captulo 2
rvore binria de busca

Uma rvore de busca uma rvore binria com a propriedade de que


para todo no x na rvore, os valores de todas as chaves na sub-rvore es-
querda so menores do que o valor chave em x, e que os valores de todas as
chaves na sub-rvore direita so maiores do que o valor chave em x. Esta
definio se aplica recursivamente a cada n da rvore. Assumimos que
cada n na rvore possui um valor chave, e em principio no considera-
da a ocorrncia de chaves repetidas. No caso das rvores representadas a
seguir, a propriedade de ordenao pode ser verificada em todos os ns na
rvore esquerda. Na rvore direita, a propriedade no se verifica uma vez
que na sub-rvore esquerda do n raiz aparece um n com chave maior (5)
quela encontrada na raiz (4).

Como a profundidade mdia das rvores binrias de busca O(log n),


as operaes sobre elas executadas tambm.
Desde que todos os elementos na rvore seguem um critrio de ordem
os operadores <, > e = podem ser aplicados de forma a estabelecer compa-
raes entre eles.

Definio do TAD rvore Binria de Busca


O conjunto de operaes necessrio para a manipulao correta e sa-
tisfatria de uma rvore binria de busca definido a seguir.

ESTRUTURA DE DADOS 71
Interface do TAD ABB

/* Retorna uma rvore vazia.


no _ ptr Inicializar (void)

/* Cria e retorna uma rvore inicializada.


no _ ptr Rriar (element _ type c, no _ ptr e, no _ ptr d)

/*Insere um dado na rvore.


int Inserir (no _ ptr pai, no _ ptr filhoEsq)

/*Busca por um determinado elemento e retorna o n corres-


pondente, ou null caso no seja encontrado.
no _ ptr Buscar (no _ ptr a, element _ type c)

/* Retorna o contedo de um n.
element _ type Conteudo (no _ ptr a)

/* Retorna o filho esquerdo de um n.


tree _ ptr retornaSAE (no _ ptr a)

/* Retorna o filho direito de um n.


tree _ ptr retornaSAD (no _ ptr a)

/*Remove o elemento de uma determinada posio.


int Remove (no _ ptr pai, no _ ptr no)

/* Retorna 1 se o n for nulo, ou 0 em caso contrrio.


int Vazia (no _ ptr a)

Implementao do TAD rvore Binria de Busca


O armazenamento de rvores pode utilizar alocao dinmica ou es-
ttica, cujas vantagens e desvantagens foram analizadas em unidades an-
teriores. No entanto, por se tratar de uma estrutura mais complexa o poten-
cial desperdcio de espao pode ser reduzido pela utilizao de ponteiros. A
definio da estrutura de dados surge naturalmente a partir da definio
recursiva da rvore. Cada n na rvore possui, alm do campo de informa-
o, dois ponteiros, que apontam para cada uma das suas sub-rvores.

typedef struct no _ rvore *no _ ptr;

struct no _ rvore {
element _ type info;
no _ ptr esq;
no _ ptr dir;
};

72 ESTRUTURA DE DADOS
Da mesma forma que uma lista encadeada representada por um
ponteiro para o primeiro n, a estrutura da rvore como um todo repre-
sentada por um ponteiro para o n raiz, a partir do qual todos os ns da
rvore podem ser alcanados.

typedef no _ ptr ABB;

Como uma rvore representada pelo endereo do n raiz, uma rvo-


re vazia tem que ser representada pelo valor NULL.

ABB Inicializar (void){


return NULL;
}

Para criar rvores no vazias, podemos ter uma operao que cria um
n raiz contendo a informao e os ponteiros s suas duas sub-rvores,
esquerda e direita. Essa funo tem como valor de retorno o endereo do
n raiz criado e inicializado, como segue:

ABB Criar (element _ type c, ABB sae, ABB sad){


p = (ABB) malloc (sizeof (no _ rvore));
p -> info = c;
p -> esq = sae;
p -> dir = sad;
return p;
}

As duas funes Inicializar e Criar representam os dois casos da defi-


nio recursiva de rvore binria: uma rvore binria vazia (a = Inicializar
();) ou composta por uma raiz e duas sub-rvores (a = Criar (c, sae, sad);).
As operaes que possibilitam a consulta dos contedos dos campos
que compem o n so apresentadas a seguir. O mtodo Conteudo retorna
a informao contida no n, enquanto que retornaSAE retorna a sub-rvore
esquerda do n. Analogamente o mtodo retornaSAD retorna a sub-rvore
direita.

char Conteudo (ABB a){


return (a -> info);
}

ABB retornaSAE (ABB a){


return (a -> esq);
}

A busca por um contedo em uma rvore binria de busca leva em


conta o critrio de ordenao estabelecido entre os ns que a compem. Des-
ta forma, enquanto a chave procurada no for encontrada, se for menor do

ESTRUTURA DE DADOS 73
que a chave que se encontra no n da rvore, a procura continua na sub-r-
vore da esquerda, e no caso contrrio na sub-rvore direita, recursivamente.

no _ ptr Buscar (element _ type x, ABB T) {


if (T == NULL) return NULL;
if (x < T -> info)
return (Buscar (x, T -> esq));
else
if (x > T -> info)
return (Buscar (x, T -> dir));
else return T;
}

O processo de insero na rvore segue a mesma lgica do algoritmo


Buscar. Se o elemento for encontrado nada feito, uma vez que no estamos
considerando a ocorrncia de chaves repetidas. Em outro caso, o elemento
inserido. Note que seja qual for a chave a ser inserida, a insero sempre
acontece em um n folha. O exemplo a seguir ilustra a insero da chave
com valor (12).

Duplicaes podem ser manipuladas mantendo um campo extra no


registro do n indicando a freqncia da ocorrncia. Esta soluo mais efi-
ciente uma vez que replicar ns na rvore tornaria a rvore mais profunda
aumentando o custo mdio requerido nas operaes sobre as rvores, alm
de alocar mais espao de memria.

no _ ptr Inserir (element _ type x, ABB T) {


if (T == NULL) {
T = (ABB) malloc (sizeof (no _ rvore));
T -> element = x;
T -> esq = T -> dir = NULL;
}
else
if (x < T -> info)
T -> esq = Inserir (x, T -> esq);

else
if (x > T -> info)
T -> dir = Inserir (x, T -> dir);
return T;
}

74 ESTRUTURA DE DADOS
Na remoo vrias possibilidades devem ser consideradas. Se o n que
vai ser removido folha a remoo imediata.
Se o n tem somente um filho ele pode ser removido ajustando os pon-
teiros entre seu pai e seu filho de modo de realizar um by pass encima do
n. Por exemplo, considere a rvore a seguir, onde o n correspondente ao
dado (5) precisa ser removido. O processo a ser seguido descrito na rvore
que aparece direita.

Se o n a ser removido tem dois filhos a estratgia geral consiste em


reemplazar a chave do n com a menor chave da sub-rvore direita (ou
maior da sub-rvore esquerda), e recursivamente remover esse n. Como
o filho mais esquerdo da sub-rvore direita no pode ter filho esquerdo, a
segunda remoo mais fcil. O exemplo a seguir ilustra a remoo do n
cujo contedo (2), que possui dois filhos. Nesse caso o n substitudo
pelo filho mais a esquerda da sub-rvore direita (ou o menor dos maiores).
Posteriormente, o n utilizado na substituio precisa ser removido (3) da
sub-rvore correspondente.

O mtodo Remover recebe por parmetro o ponteiro ao n que ser re-


movido. Este ponteiro pode ter sido obtido a partir da execuo da operao
de busca por um contedo especfico. O algoritmo tambm precisa do pon-
teiro correspondente ao n pai do n que ser removido, j que o respectivo
ponteiro precisa ser ajustado.
O cdigo realiza dois passes na rvore para encontrar e remover o
menor n da sub-rvore direita. Esta ineficincia pode ser removida escre-
vendo uma funo delete_min.

ESTRUTURA DE DADOS 75
void Remover (element _ type x, ABB pai, ABB no){
no _ ptr tmp _ no, filho;

if (no -> esq != null && v -> dir != null) {


tmp _ cell = buscaMin (no -> dir);
no -> info = tmp _ cell -> info;
no -> dir = Remover (no -> info, no -> dir);
}

else {
tmp _ no = no;
if(no -> esq == NULL
filho = no -> dir;
if(no -> dir == NULL )
filho = no -> esq;
if (pai -> dir ==T)
pai -> dir = filho;
else
pai -> esq = filho;

free (tmp _ no);


}
}

O mtodo auxiliar que procura o n que contem o contedo mnimo


possui duas verses, uma recursiva e outra iterativa.

no _ ptr buscaMin (ABB T){


if (T == NULL ) return NULL;

else
if (T -> esq == NULL )
return (T);
else return (buscaMin (T -> esq));
}

no _ ptr buscaMin (ABB T){


if (T != NULL)
while (T -> esq != NULL)
T = T -> esq;
return T;
}
Os dois algoritmos possuem uma lgica simples, no entanto a verso
no recursiva pode ser mais eficiente em termo de custo espacial e temporal
do que a verso recursiva.

76 ESTRUTURA DE DADOS
Escreva uma funo que verifi que se uma rvore cheia. Uma rvore
dita cheia se todos os ns que no so folhas tm os dois fi lhos, isto ,
no pode existir n com apenas um fi lho. A funo deve retornar 1 no caso
da rvore ser cheia ou 0 no caso de no ser. No caso da rvore ser vazia, a
funo deve retornar 1.

int cheia (tree _ ptr a) {


if (vazia (a))
return (1);
else
if ((vazia (retornaSAE (a)) && !vazia
(retornaSAD (a)) ||((!vazia (retornaSAE (a))
&& vazia (retornaSAD(a))
return (0);
else
return cheia (retornaSAE (a)) && cheia
(retornaSAD(a));
}

Ordens de percurso em rvores binrias


O percurso de todas as sub-rvores executando alguma ao de trata-
mento em cada n, pode ser feito seguindo uma das seguintes ordens:
pr-ordem: trata raiz, percorre sae, percorre sad;
ordem simtrica: percorre sae, trata raiz, percorre sad;
ps-ordem: percorre sae, percorre sad, trata raiz.

Por exemplo, no caso de imprimir o contedo dos ns de uma rvore


binria, os algoritmos que implementam esta ao de acordo com cada per-
curso so apresentados a continuao.

void ImprimirPosordem (no _ ptr a){


if ( !Vazia(a) ){
ImprimirPosordem (retornaSAE(a));
ImprimirPosordem (retornaSAD(a));
printf (Conteudo(a));
}
return;
}

ESTRUTURA DE DADOS 77
void ImprimirSimetrica (no _ ptr a){
if ( !Vazia(a) ){
ImprimirSimetrica (retornaSAE(a));
printf (Conteudo(a));
ImprimirSimetrica (retornaSAD(a));
}
return;
}

void ImprimirPreordem (no _ ptr a){


if ( !Vazia(a) ){
printf (Conteudo(a));
ImprimirPreordem (retornaSAE(a));
ImprimirPreordem (retornaSAD(a));
}
return;
}

Por exemplo, dada a rvore de expresso a seguir, como resultado dos


percursos apresentados, as expresses resultantes so as seguintes:

Inordem: 5 + 9 * 3 - 7 + 7
Preordem: + * +5 9 3 7 7
Posordem: 5 9 + 3 7 - * 7 +

1. Crie a rvore binria de acordo com a seguinte sequncia de nmeros,


na ordem:
a) 1, 2, 3, 4, 5, 6, 7. Analise a rvore binria obtida em termo de desem-
penho na execuo das operaes sobre ela.
b) 20, 5, 12, 36, 27, 45, 9, 2, 6, 17, 40.

78 ESTRUTURA DE DADOS
c) A partir da rvore obtida no inciso anterior, remover os ns: 9, a seguir
o 5, e fi nalmente o 20.
2. Implemente um algoritmo que determine se uma rvore binria de busca
efetivamente uma rvore binria de busca.
3. Implemente o mtodo que retorna o maior elemento a partir de um deter-
minado n cujo cabealho : no _ ptr buscaMAX (ABB T). Implemente
o mtodo na sua verso recursiva e no recursiva.
4. Dada uma rvore binria de busca, onde cada n constitudo pelas
seguintes informaes: NOME, SEXO (M ou F), IDADE e PESO. Sa-
bendo que a rvore foi construda com a chave NOME e que j existe um
ponteiro chamado RAIZ que aponta para o n raiz da rvore, construir
um algoritmo que, a partir desta rvore, gere duas listas ordenadas por
NOME, uma para homens e outra para mulheres.
5. Escreva um algoritmo recursivo que encontre o maior valor armazenado
em uma rvore binria de busca j construda.
6. Adapte os algoritmos de insero e remoo em rvores binrias de bus-
ca de forma a tratar a ocorrncia de contedos-chave repetidos, manten-
do um contador de ocorrncias em cada n.
7. Para a rvore binria a seguir, escreva as sequncias de ns visitados
aps a execuo dos percursos pr-ordem, inordem e ps-ordem. Codifi -
que os algoritmos correspondentes a cada um dos percursos.

8. Utilizando as operaes defi nidas na interface do TAD ABB de nmeros,


escreva um mtodo que retorne quantos ns de uma ABB armazenam
valores contidos em um intervalo [x1, x2].

Relao entre o nmero de ns de uma rvore


binria e sua altura
A cada nvel o nmero potencial de ns numa rvore binria vai dobran-
do, de forma que para uma altura h da rvore existe um nmero mximo de
ns, dado por:
2 0
+2 1
+2 2
+ ... + 2 h-1
+2 h
=2 h+1
- 1 ns

ESTRUTURA DE DADOS 79
Portanto, uma AB de altura h pode ter no mximo O (2h) ns. A partir
desta definio temos que o nmero de ns em uma AB dada por n = 2h
ns. Para despejar h temos que aplicar a definio de logaritmo: log n = h.
log 2. Portanto uma rvore binria com n ns pode ter uma altura mnima de
O (log n).
Por outro lado, se a rvore tem altura h, deve existir um caminho de
comprimento h da raiz at um dos ns, digamos n0, n1, ... nh, e todos os h+1
ns deste caminho devem ficar em nveis diferentes. Assim, a rvore dever
ter pelo menos h+1 ns.
Esta relao entre o nmero de ns e a sua altura importante, pois
significa que a partir da raiz, qualquer n pode ser alcanado em no mximo
O (log n) passos. Note que se tivssemos n ns numa lista linear o nmero
mximo de passos seria O (n).
A altura da rvore uma medida do tempo necessrio para encontrar
um n. Esta propriedade atinge a eficincia mxima quando a rvore binria
balanceada, ou seja, todos os ns internos, ou quase todos possuem dois
filhos.
fcil prever que aps vrias operaes de insero e remoo, a rvore
tende a ficar desbalanceada. Em especial, a operao de remoo numa ABB
dependendo da estratgia utilizada (substituio do n a ser removido pelo
maior da sub-rvore esquerda ou o menor da sub-rvore direita), favorece
sistematicamente uma das sub-rvores.
A soluo a este problema consiste em sempre manter a altura das sub-
rvores no mnimo, ou prximo do mnimo. Para isso necessrio de proces-
sos de insero e remoo mais complexos que mantenham as sub-rvores
balanceadas.

80 ESTRUTURA DE DADOS
Captulo 3
rvores AVL

Uma AVL uma rvore binria de busca dinamicamente equilibrada


ou balanceada, na qual se busca manter, a um custo razovel, um tempo
de busca prximo quele que se conseguiria se a rvore fosse completa, o
que garante que a altura da rvore O(log n). O nome AVL deve-se aos seus
criadores, os matemticos ADELSON-VELSKII e LANDIS.
A propriedade de balanceamento consiste em manter as sub-rvores
esquerda e direita de cada n, na mesma altura, podendo diferir no mximo
em 1 nvel. A figura a seguir ilustra uma rvore, onde a raiz se encontra
balanceada uma vez que a suas sub-rvores esquerda e direita possuem a
mesma altura, no entanto os ns internos no satisfazem essa propriedade.

Com esta restrio, todas as operaes sobre rvores podem ser exe-
cutadas em tempo O(log n), exceto possivelmente a insero. No entanto,
para manter a propriedade de balanceamento, alm dos algoritmos de per-
curso, incluso e excluso j discutidos, so necessrios algoritmos que
restabeleam o equilbrio aps incluses e excluses, caso algum n fique
desregulado. Por exemplo, na insero, pode ser preciso atualizar a infor-
mao de balanceamento para os ns no caminho de volta para a raiz, pois
somente aqueles ns tiveram as suas sub-rvores alteradas. No caso das
rvores binrias de busca representadas a seguir, a rvore da esquerda se
encontra balanceada uma vez que todos os ns mantem suas sub-rvores
com uma diferena de at um nvel. J a rvore da direita apresenta um
desbalanceamento na raiz.

ESTRUTURA DE DADOS 81
A insero de 6.5 na primeira rvore provocar o desbalanceamento
do n 8. A propriedade de balanceamento restaurada atravs de operaes
de rotao.
Seja o no desbalanceado. Desde que todo n tem no mximo dois
filhos e o desbalanceamento da altura requer que a altura das duas sub-
rvores deferem em 2, a violao da propriedade pode acontecer como con-
sequncia de operaes de insero ou remoo.
O fator de balanceamento (FB) de um determinado n r calculado
como a diferencia entre a altura da sub-rvore esquerda de r e da sub-rvo-
re direita de r. Se o valor obtido for menor ou igual a 1 o n est balanceado.
Caso contrrio o n se encontra desbalanceado. O FB de um n folha 0.

Algoritmo que calcula a altura de um n

int Altura (ABB no){


int Alt _ Esq, Alt _ Dir;

if (no = NULL)
Altura := -1
else {
Alt _ Esq := Altura (retornaSAD (no));
Alt _ Dir := Altura (retornaSAE (no));

if (Alt _ Esq > Alt _ Dir)


Altura := 1 + Alt _ Esq
else Altura := 1 + Alt _ Dir;
}
}

No caso em que for constatado o desbalanceamento em um determi-


nado n, quatro situaes possveis podem ser constatadas.
Tipo I : Se a sub-rvore esquerda maior que a sub-rvore direita
(FB > 1), e a sub-rvore esquerda desta sub-rvore esquerda maior
que a sub-rvore direita dela, ento realizar uma rotao simples
para a direita;

Tipo II : Se a sub-rvore esquerda maior que a sub-rvore direita


(FB > 1), e a sub-rvore esquerda desta sub-rvore esquerda me-

82 ESTRUTURA DE DADOS
nor ou igual que a sub-rvore direita, ento realizar uma rotao
dupla para a direita;

Tipo III: Se a sub-rvore esquerda menor que a sub-rvore direita


(FB < -1), e a sub-rvore direita desta sub-rvore direita menor ou
igual que a sub-rvore esquerda dela, ento realizar uma rotao
dupla para a esquerda;

Tipo IV: Se a sub-rvore esquerda menor que a sub-rvore direita


(FB < -1), e a sub-rvore direita desta sub-rvore direita maior que
a sub-rvore esquerda dela, ento realizar uma rotao simples
para a esquerda.

A partir das situaes apresentadas, qualquer tipo de desbalancea-


mento pode ser corrigido aplicando uma das 4 rotaes descritas.

Exemplo
Comeando a partir de uma rvore vazia, so inseridos os nmeros de
(1), (4) e (7). O primeiro problema acontece na insero do (7): a propriedade

ESTRUTURA DE DADOS 83
de balanceamento violada na raiz. Para resolver executada uma rotao
simples a esquerda.

A seguir inserida a chave (9), sem prejuzo do balanceamento da


rvore. A insero do (8) provoca uma nova violao no n (7) (e tambm na
raiz da rvore). Repare que neste caso uma rotao simples a esquerda no
resolve o problema.

O desbalanceamento no n (7) resolvido em dois passos, atravs de


uma rotao dupla a esquerda. No primeiro passo realizada uma rota-
o simples a direita envolvendo a sub-rvore do n desbalanceado. J no
segundo passo, uma rotao a esquerda envolvendo o n desbalanceado
devolve o balanceamento rvore.

A insero do (12) provoca o desbalanceamento da raiz desde que a


sub-rvore esquerda de altura 0, enquanto que a direita tem altura 2. para
resolver executada uma rotao simples a esquerda.

84 ESTRUTURA DE DADOS
Como resultado da rotao, o n com a chave (8) se torna a nova raiz
da rvore, e com isso, a sua sub-rvore esquerda (7) se transforma na nova
sub-rvore direita do (4).
Continuando o exemplo, a insero da chave (10) desbalanceia o n
(9), desencadeando uma nova rotao dupla a esquerda.

importante salientar q ue se a rvore no fosse AVL, o resultado das


inseres teria gerado uma rvore de altura 5, enquanto que a AVL obtida a
partir da mesma sequencia de insero possui altura 2.

1. Considerando que a altura (h) de uma rvore dada pelo caminho mais
longo desde a raiz at uma folha, explique com as suas palavras a re-
lao existente entre altura (h) de uma rvore binria e a quantidade
(mnima e mxima) de ns.
a) Qual a relao entre a altura (h) de uma rvore e o tempo requerido
(custo) para encontrar um n?
b) Em qual situao a busca em uma rvore binria pode atingir efi ci-
ncia mxima?

ESTRUTURA DE DADOS 85
2. Defi na uma rvore AVL estabelecendo as suas propriedades, vantagens
e desvantagens da sua utilizao.
3. Dada a seguinte rvore (binria de busca) AVL, simule o processo de in-
sero e remoo das seguintes chaves na rvore na ordem dada: inser-
o 25 - insero 70 - insero 15 - insero 12 - insero 18 - remoo
15. Verifi que a cada passo se a propriedade de balanceamento continua
sendo mantida. Em caso de desbalanceamento, indicar o n desbalance-
ado e as operaes de rotao indicadas para resolver o problema.

4. Considerando a seguinte sequncia de caracteres: A, Z, B, Y, C, X, D, P,


E, V, F. Simule a construo passo a passo de uma rvore AVL de carac-
teres, e indique em que situaes ocorrem rotaes simples ou duplas,
direita ou esquerda, dos vrios elementos da rvore.
5. Considerando a seguinte sequncia de nmeros: insero 50, insero
20, insero 30, insero 25, insero 10, insero 15, remoo 20, in-
sero 20, insero 40. Simule a construo passo a passo de uma rvo-
re AVL de nmeros com a sequncia acima, e indique em que situaes
ocorrem rotaes simples ou duplas, direita ou esquerda, dos vrios
elementos da rvore.

Nesta unidade foram apresentados os conceitos fundamentais sobre


rvores e rvores binrias. O TAD rvore Binria de Busca foi defi nido e im-
plementado, e alguns exemplos de utilizao foram ilustrados, assim como
os diferentes percursos possveis sobre a estrutura.
Adicionalmente, a conceituao sobre rvores binrias balanceadas, e
sua importncia em relao ao aumento no desempenho das operaes re-
alizadas foi relatada. A propriedade de balanceamento e as estratgias para
restabelecer o equilibrio na rvore foram detalhados e ilustrados.

86 ESTRUTURA DE DADOS
AHO, J.E. Hopcroft, and J.D. Ullman. Data structures and algorithms.
Addison-Wesley, Reading, Mass., 1983.
CORMEN T. H., LEISERSON C. E., RIVEST R. L., STEIN C. (2001). Intro-
duction to Algorithms. McGraw-Hill e The Mit Press.
HOROWITZ and S. Sahni (1987). Fundamentals of data structures, Com-
puter Science Press. Editora Campus.
KNUTH D. E. (1968). The Art of Computer Programming, Vol. 1: Funda-
mental Algorithms. Addison-Wesley.
SZWARCFITER J. l., MARKENZON L. (2010). Estruturas de Dados e Seus
Algoritmos. 3. Edio. LTC.
ZIVIANI N. (2005). Projeto de Algoritmos com implementaes em Pas-
cal e C, 2da. Edio. Thomson.

ESTRUTURA DE DADOS 87
Unidade

5
Busca avanada

Objetivos:
A eficincia alcanada para resolver o problema da busca ou recuperao de
informao a partir de uma estrutura de dados um indicador da eficincia da
estrutura. Nesta unidade so apresentados mtodos especficos de busca que
objetivam reduzir a complexidade em relao aos mtodos de busca padro
apresentados em unidades anteriores. Em particular, apresentado o uso de
tabelas de ndices que possibilitam o acesso direto informao, idealmente. No
domnio especifico de tratamento de cadeias a busca digital apresentada como
soluo para o problema de casamento de padres. Finalmente, o funcionamento
de estruturas auto-ajustveis descrito.
Captulo 1
Tabela de disperso

O armazenamento e recuperao da informao so possivelmente as


funcionalidades mais importantes requeridas de um computador. De forma
geral, a informao organizada em estruturas que possibilitam que os da-
dos possam ser recuperados da memria e interpretados quando necessrio.
A pesquisa por um determinado dado requer que seja estabelecido
um critrio, que geralmente baseado na existncia de uma chave de pes-
quisa que possibilita que ocorrncias da informao sejam corretamente
identifi cadas.
Diversas estratgias podem ser utilizadas para realizar uma pesquisa
por registros em uma tabela. A escolha pela mais adequada depende prin-
A chave de pesquisa o
cipalmente das necessidades e caractersticas da aplicao especfi ca. Os campo do registro a par-
dois principais fatores que infl uenciam nesta escolha so o tamanho da tir do qual o registro pode
entrada, ou seja a quantidade de elementos a serem processados e as ope- ser referenciado de forma
raes mais frequentemente executadas sobre a estrutura. unvoca. Cada registro no
conjunto possui um cam-
Existem diversos mtodos de pesquisa amplamente utilizados. Den- po chave nico o que pos-
tre eles, a pesquisa sequencial o mtodo mais simples onde, a partir do sibilita a sua identifi cao
a partir dele.
primeiro registro, a pesquisa realizada em forma sequencial seguindo a
ordem apresentada pelos elementos. O processo continua at que a chave
for encontrada ou a tabela for percorrida completamente sem sucesso. Esta
estratgia foi utilizada no mtodo de busca implementado no TAD Lista. O
esforo requerido nesta busca O(n), uma vez que no pior cenrio, a lista
precisar ser percorrida na sua totalidade.
A rvore de busca e suas variantes abordada na Unidade 4 uma
estrutura de dados muito efi ciente para armazenamento e recuperao de
informao. Neste caso, o custo demandar em mdia O(log n).
Tanto a pesquisa sequencial como a aplicada em rvores de busca, so
baseadas na comparao entre chaves. Diferentemente, a tcnica baseada
em transformao de chave ou hashing utiliza uma funo de transforma-
o aritmtica a partir da qual uma chave mapeada para um endereo de
memria utilizando as chamadas tabelas de disperso ou tabelas de hash.
A seguir o funcionamento da tabela de disperso apresentado.
Seja, por exemplo, a distribuio de expedientes de funcionrios de
uma empresa ao longo de um arquivo de pastas, onde cada pasta indica
a inicial do sobrenome do funcionrio. A principio considerado que no
existe ordem para a colocao dos expedientes dentro de cada pasta do
arquivo. Nesse caso o sobrenome seria a chave e a inicial o endereo de ar-
mazenamento.
Em cincia da computao a tabela de disperso (de hashing, no in-
gls), uma estrutura de dados especial, que associa chaves de pesquisa
a valores. Seu objetivo , a partir de uma chave simples, fazer uma busca
rpida e obter o valor desejado em tempo constante.

ESTRUTURA DE DADOS 91
A utilizao de tabela de disperso para o armazenamento e recupe-
rao da informao visa tornar estas operaes mais efi cientes em termos
de esforo, em relao aos outros mecanismos de busca estudados, alcan-
ando uma complexidade mdia de O(1). O ganho com relao a outras es-
truturas associativas (como um vetor simples) passa a ser maior conforme
a quantidade de dados aumenta. Em contrapartida, em uma tabela de dis-
perso virtualmente impossvel estabelecer uma ordem para os elementos.
Em outras palavras, a funo de disperso estabelece uma indexao sobre
as chaves mas no preserva a ordem entre elas.
O mtodo de pesquisa com uso de transformao de chave envolve
duas etapas.
1. Desenvolver e aplicar a funo de transformao aritmtica do valor
da chave para um endereo na memria.
A ocorrncia de colises 2. Dependendo da quantidade de chaves e da efi cincia da funo de
pode ser abordada do
ponto de vista probabilis-
transformao na gerao de endereos, pode ser necessrio ela-
tico. O paradoxo do ani- borar uma estratgia de tratamento para colises para tratar os
versrio estabelece que, casos em que duas chaves gerem o mesmo endereo.
se tomadas aleatoriamen-
te 50 pessoas, pelo menos Considere a existncia de n chaves a serem armazenadas na tabela T,
duas pessoas teriam a de dimenso m. A tabela considerada uma estrutura sequncial, portanto
mesma data de anivers-
rio ou coliso. as posies ou endereos se encontram no intervalo [0, m 1]. Se o nmero
de chaves n for igual ao nmero de posies na tabela, m, e, alm disso, os
valores das chaves forem de 0 a m 1, ento, cada chave x poderia ser ar-
mazenada no endereo x correspondente.
Tabelas de disperso so tipicamente utilizadas para indexao de
grandes volumes de informao, tais como bases de dados. Outros exem-
plos de uso das tabelas de disperso so as tabelas de transposio em
jogos de xadrez para computador.

A funo de disperso
A funo de disperso a responsvel por gerar um ndice a partir de
determinada chave. A defi nio da funo de fundamental importncia,
uma vez que se no for adequada para o tratamento dos dados em questo,
a manipulao da tabela ter um mau desempenho.
O ideal para a funo de disperso que sejam sempre fornecidos
ndices nicos para as chaves de entrada. A funo perfeita seria a que,
para quaisquer entradas A e B, sendo A diferente de B, fornecesse sadas
diferentes. Quando as entradas A e B so diferentes e, passando pela fun-
o de disperso, geram a mesma sada, acontece uma coliso. De forma
simplifi cada temos que: Pos (elemento) = H (elemento, n), onde H a funo
de disperso aplicada ao elemento, considerando o tamanho n da tabela.

92 ESTRUTURA DE DADOS
No exemplo, a funo de disperso aplicada sobre a chave nome,
para obter um ndice de acesso ao vetor onde o registro armazenado. O
registro pode agregar vrios campos de informao, alm do campo chave.
No entanto, na prtica, difcil encontrar uma funo de disperso
perfeita que consiga espalhar de forma uniformemente esparsa as chaves
ao longo da estrutura. Dando sequncia ao exemplo acima, a aplicao da
funo de disperso para o nome Luiza pode vir a gerar o mesmo ndice do
que Luiz (790), provocando uma coliso. Esta situao indesejvel uma vez
que reduz o desempenho do sistema. No entanto muito comum acontecer,
por isso que diversas tcnicas de tratamento de colises tem sido propos-
tas na literatura.

Exemplo de funo de disperso


Uma funo de disperso muito simples envolve transformar um ca-
racter em um valor numrico. Isto, na linguagem C, poderia ser feito da
seguinte forma: Na prtica, funes de
disperso perfeitas ou
quase perfeitas so en-
int hashExemplo(char * chave) { contradas apenas onde a
coliso intolervel, como
return (chave[0]-65); por exemplo em aplica-
es de criptografi a, ou
}
quando o contedo da ta-
bela armazenada conhe-
cido previamente.
Dada sua simplicidade esta funo causaria muitas colises, no en-
tanto pode ser utilizada como parte de uma funo mais complexa que
possibilite um melhor espalhamento dos dados.

ESTRUTURA DE DADOS 93
1. Defi na o conceito de tabela de disperso e descreva o processo envolvido
na aplicao desta tcnica.
2. Estabelea vantagens e desvantagens em relao a outros mecanismos
de armazenamento e recuperao de informao.
3. Pesquise na literatura sobre funes de disperso comumente utilizadas
e que tem demostrado desempenho aceitvel.
a) Mtodo da diviso
b) Mtodo da dobra
4. Apresente um exemplo prtico de gerao de uma tabela de disperso
utilizando os mtodos pesquisados no item anterior.

O tratamento das colises envolve geralmente a utilizao de alguma


outra estrutura de dados em conjuno com as tabelas de disperso, tal
como uma lista encadeada ou at mesmo rvore rvores balanceadas (AVL).
Em outras oportunidades a coliso solucionada dentro da prpria tabela.

Estratgias para resoluo de colises


Considerando que a ocorrncia de colises praticamente inevitvel,
um bom mtodo de resoluo de colises essencial, independentemente da
qualidade da funo de disperso utilizada.
H diversos algoritmos de resoluo de coliso, mas os mais conheci-
dos so os de encadeamento e sondagem.

Encadeamento
A utilizao de listas encadeadas a soluo mais simples para o
tratamento de colises. Neste caso, a partir do ndice em confl ito mantido
um ponteiro para uma lista encadeada onde so armazenados os registros
em confl ito. A insero na tabela requer e insero dentro da lista encade-
ada. Analogamente, a remoo requer atualizar os ndices dentro da lista.
O TAD lista na sua verso encadeada atravs de ponteiros foi apresentado
na Unidade 3.
Grafi camente, a soluo de colises atravs de listas encadeadas
representada a seguir. A situao de coliso entre as chaves Luiz e Luiza
seria resolvida adicionando o registro correspondente chave repetida na
lista associada ao ndice.

94 ESTRUTURA DE DADOS
Esta soluo adiciona um nvel de indireo s operaes de insero
e recuperao da informao, uma vez que o registro no mais acessado
diretamente a partir da chave, no entanto, o custo de acesso continua se
mantendo baixo. Estruturas de dados alternativas podem ser utilizadas no
lugar das listas encadeadas. Por exemplo, a partir da utilizao de rvores
binrias balanceadas (AVL) possvel melhorar o tempo mdio de acesso
da tabela disperso para O(log n) ao invs de O(n) demandado no caso da
utilizao de listas.

Tcnicas de sondagem
Em contrapartida tcnica de encadeamento, as tcnicas de sonda-
gem para o tratamento de colises no fazem uso de nenhuma estrutura
auxiliar para o armazenamento da informao. Em caso de coliso, os re-
gistros em conflito so armazenados dentro da prpria tabela, utilizando
buscas padronizadas at encontrar um registro vazio ou o registro buscado.
Outras formas mais complexas de implementar a tcnica de sondagem
consiste em determinar a posio do novo elemento em coliso a partir de
uma funo quadrtica, incrementando o ndice exponencialmente. Desta
forma, caso a chave procurada no se encontre na posio 10, em uma se-
gunda tentativa ser procurada na posio 100, 1000, e assim por diante.
Uma terceira possibilidade envolve a aplicao de uma nova funo
de disperso (tambm chamado de double hashing), cuja chave de entrada
ser o valor gerado pela funo anterior. Esta soluo pode ser til em casos
muito especficos, com enormes quantidades de dados, no entanto a sobre-
carga no sistema nem sempre justifica a experincia.

ESTRUTURA DE DADOS 95
1. Explique o conceito de coliso e por que acontecem.
2. Pesquise as diferentes formas de resoluo de coliso e analise suas van-
tagens e desvantagens. Exemplifi que.

96 ESTRUTURA DE DADOS
Captulo 2
Busca digital

O problema de busca geralmente considera a comparao entre uma


chave desejada e as chaves que compem um conjunto, que pode ser estru-
turado de formas convenientes no intuito de melhorar o desempenho das
operaes. Diferentemente, no caso da busca digital, a chave constituida
de um conjunto de caracteres ou dgitos pertencentes a um alfabeto apro-
priado. Neste caso especfi co, a comparao entre chaves realizada dgito
a dgito, individualmente.
A busca digital funciona de forma similar busca em dicionrios, de-
compondo a palavra letra a letra (caracter ou dgito), onde a primeira letra
da palavra determina um ndice de pgina onde se encontram as palavras
iniciadas por aquela letra. As cadeias aparecem no
Os mtodos de busca digital so particularmente teis quando as processamento de texto
em linguagem natural, di-
chaves so grandes e de tamanho varivel. A partir desta pesquisa pos- cionrios, sequenciamen-
svel localizar todas as ocorrncias de uma determinada cadeia em um tex- to de DNA, processamento
to, com tempo de resposta O(log n) em relao ao tamanho do texto. Este de imagens, etc. Em cada
domnio, um alfabeto es-
problema conhecido como casamento de cadeias, no contexto de proces- pecfi co utilizado. Exem-
samento de cadeias de caracteres. plos de alfabetos: {0, 1}, {a,
O processamento de cadeias de caracteres envolve duas classes de b, c, ..., z}, {0, 1, ... 9}.

problemas: casamento de cadeias (do ingls, pattern matching) e compres-


so de cadeias.
O problema de casamento de cadeias envolve a procura pela ocorrn-
cia de um determinado padro em um texto que est sendo editado. For-
malmente, o texto T considerado um vetor de tamanho n e o padro P um
vetor de tamanho m, com m < = n. Os elementos que compem T e P perten-
cem a um alfabeto fi nito de tamanho c. Dadas duas cadeias T e P, deseja-se
saber as ocorrncias de P em T.
A compresso de texto est relacionada com a representao de um
texto original de forma a ocupar menos espao, ou seja utilizando um n-
mero menor de bits.
Mtodos mais modernos de compresso de cadeias possibilitam o
acesso direto a texto comprimido sem necessidade de descomprimir o texto,
permitindo melhorar a efi cincia de sistemas de recuperao de informao
e aumentar a economia de espao.
No, mtodo de busca digital, tanto o padro procurado quanto o texto
so pr-processados a partir da construo de ndices de forma a reduzir a
complexidade das operaes para um custo O(log n). No entanto, o tempo de
pr-processamento compensado por muitas operaes de busca.
A seguir so apresentados brevemente os tipos de ndices mais conhe-
cidos para o pr-processamento de cadeias de forma a agilizar o desempe-
nho das buscas.

ESTRUTURA DE DADOS 97
rvore digital
A estrutura mais apropriada para realizar a busca digital atravs da
rvore digital.
Formalmente, uma sequncia S = {s1, ..., sn} um conjunto de n chaves
em que cada si formada por uma sequncia de elementos dj denominados
dgitos. Supe-se que existe em S o total de m dgitos distintos que determi-
nam o alfabeto ordenado de S. Os primeiros p dgitos de uma chave com-
pem o prefi xo de tamanho p da chave.
Uma rvore digital para S uma rvore m-ria T, no vazia, tal que:
1. Se o n v o j-ssimo fi lho de seu pai, ento v corresponde ao dgito
dj do alfabeto S, 1 <= j <= m.
2. Para cada n v, a sequncia de dgitos defi nida pelo caminho desde
a raiz de T at v corresponde a um prefi xo de alguma chave de S.
Na anlise de um texto em linguagem natural, S seria o conjunto de
frases do texto, onde si cada frase que pode ser buscada e n o nmero de
frases, e m = 26.
Em um caso especfi co da rvore digital, no entanto o mais utilizado,
temos a rvore digital binria, onde o grau da rvore m = 2. O alfabeto
considerado neste caso {0, 1}. A partir da construo da rvore digital com
estas caractersticas, as chaves a serem consideradas nas buscas envolvem
sequncias binrias.

Chaves rvore digital binria


00

0010

010

010111

010110

00100

11

110

1101

A partir da rvore gerada possvel observar que algumas chaves


binrias so prefi xos de outras chaves pertencentes mesma coleo. Por
exemplo, o caminho da raiz at o n com contedo correspondente chave
010 que prefi xo da chave 010110 correspondente ao caminho at o n .
Cada n na rvore pertence a uma chave (ou mais) do conjunto. Por
exemplo o n com corresponde chave 010, e faz parte (prefi xo) das chaves
010111 e tambm 010110. De acordo com a implementao da rvore digital,
cada n na rvore envolve um campo adicional contendo um ponteiro para
a informao correspondende chave detectada. Por exemplo, no caso do n
existiria um ponteiro de forma a localizar no texto a chave 010. Os pon-
teiros de ns que no correspondem ao ltimo dgito de uma chave vlida
seriam nulos (NULL).

98 ESTRUTURA DE DADOS
Uma vez criada a rvore, a busca acontece como resultado do percur-
so a partir da raiz: o fi lho esquerdo representa o dgito 0 e o fi lhor direita
representa o dgito 1. Note que a busca localiza no somente uma chave
vlida completa, mas tambm prefi xos. A busca por prefi xos pode ser de
grande utilidade dependendo da aplicao, como por exemplo lingustica.

1. Explique como funciona a busca digital e seu papel no contexto de pro-


cessamento de cadeias. Mencione reas de aplicao deste tipo de busca.
2. Pesquise sobre compresso de textos em linguagem natural.
3. Crie grafi camente uma rvore digital binria a partir do seguinte con-
junto de chaves: 00, 0000, 00010, 00011, 0101100, 0101101, 10, 101,
1010.

ESTRUTURA DE DADOS 99
Captulo 3
Estruturas autoajustveis

As operaes de insero e remoo de elementos aplicadas sobre uma


determinada estrutura de dado afetam necessariamente a forma da estru-
tura. J a operao de busca inocua no sentido em que, a principio, no
produz nenhuma alterao na forma da estrutura. No caso de estruturas
autoajustveis, a operao de busca pode alterar a forma da estrutura de
dado objetivando melhorar o desempenho em buscas futuras. Por exemplo,
no caso de ser detectada certa frequncia na procura por um determinado
componente em uma lista ou rvore, a posio ou nvel do componente na
lista ou na rvore, respectivamente, pode ser alterado, de forma a agilizar
as futuras buscas pelo mesmo componente.
A partir deste comportamento, a complexidade ordinria de uma ope-
rao calculada individualmente, e de forma independente, para o pior caso
na sua execuo no mais adequada. Em contrapartida, a complexida-
de amortizada considera a configuraes da estrutura ao longo de uma
sequncia de operaes executadas, avaliando as consequncias de cada
execuo, de forma acumulada.
O conceito de autoajuste pode ser aplicado a diversas estruturas de
dados, tais como listas, conjuntos e rvores.

Listas autoajustveis
O TAD Lista foi abordado na Unidade 3. Como foi visto, o tipo lista
pode ser implementado utilizando a abordagem de alocao de memria
esttica (vetores) ou dinmica (ponteiros). Considerando que na sua verso
mais simples no estabelecido um critrio de ordenao entre os elemen-
tos, alguns elementos na lista podem ser requisitados mais frequentemente
do que outros. A partir desta constatao, uma lista autoajustvel imple-
menta estratgias para reduzir o tempo de acesso em operaes subsequen-
tes. A estratgia geral consiste em posicionar os ns mais procurados mais
prximos do inicio da lista, de forma que em futuras buscas possam ser
alcanados mais rapidamente. Esta estratgia pode ser implementada uti-
lizando diversos mtodos.
O mtodo de mover para frente transfere o n procurado para o inicio
da lista. Repare que dependendo da implementao utilizada para imple-
mentar a lista, esta operao pode ser custosa. Por outro lado, ns com bai-
xa probabilidade de acesso podem ser eventualmente acessados, tornando
mais custosas as buscar por ns com maior probabilidade.
No mtodo de transposio uma vez acessado o n procurado, este
transferido para a posio imediatamente anterior. Na medida em que o n
for acessado, mais prximo do inicio ser posicionado.
A implementao do mtodo de contador de frequncias envolve a in-
corporao de um campo adicional na estrutura do n da lista, responsvel

100 ESTRUTURA DE DADOS


por manter o nmero de acessos efetuados ao respectivo n. Este campo
utilizado como chave para a ordenao decrescente dos elementos na lista.
Ou seja que os ns mas frequentemente acessados so localizados no inicio,
e portanto mais rapidamente alcanados.
Alguns mtodos hbridos envolvem a combinao dos mtodos ante-
riores de forma a tirar vantagem dos benefi cios e reduzir as desvantagens
dos mtodos no seu formato individual.

1. Explique o funcionamento das estruturas de dados autoajustveis.


2. Quais seriam as adaptaes requeridas para que o TAD Lista apresenta-
do na Unidade 3 se torne TAD Lista Autoajustvel?
a) Defi na a nova estrutura de dados.
b) Implemente ou adapte as operaes necessrias.
3. Pesquise sobre uma outra estrutura estudada ao longo desta disciplina
que possa se tornar autoajustvel. Descreva as caractersticas de fun-
cionamento e as adaptaes necessrias.

Nesta unidade foram apresentadas diversas estratgias para arma-


zenamento e recuperao de informao. Inicialmente foram apresentadas
as tabelas de disperso ou hash, como uma soluo para o acesso direto
ou semidireto informao a partir da gerao de ndices, obtidos como
resultado de um processo de transformao tendo como base o valor chave
do registro. Mecanismos de tratamento de colises no caso de gerao de
ndices repetidos foram indicados.
Em relao ao processamento de cadeias de caracteres, foi apresenta-
da a teoria sobre busca digital, que possibilita estabelecer o casamento de
chaves, constitudas por caracteres ou dgitos, e texto. Com este objetivo, a
estrutura de rvore digital foi apresentada.
Finalmente, o funcionamento de estruturas autoajustveis, com foco
na sua exemplifi cao atravs de listas foi descrito, indicando as estratgias
de implementao a serem seguidas.
De forma geral, todos estes mecanismos e estratgias objetivam tornar
mais efi ciente o armazenamento e posterior recuperao da informao, de
forma a tornar os algoritmos mais acessveis e capazes de lidar melhor com
a complexidade cada vez maior requerida pelas aplicaes atuais.

ESTRUTURA DE DADOS 101


AHO, J.E. Hopcroft, and J.D. Ullman. Data structures and algorithms.
Addison-Wesley, Reading, Mass., 1983.
CORMEN T. H., LEISERSON C. E., RIVEST R. L., STEIN C. (2001). Intro-
duction to Algorithms. McGraw-Hill e The Mit Press.
HOROWITZ and S. Sahni (1987). Fundamentals of data structures, Com-
puter Science Press. Editora Campus.
KNUTH D. E. (1968). The Art of Computer Programming, Vol. 1: Funda-
mental Algorithms. Addison-Wesley.
SZWARCFITER J. l., MARKENZON L. (2010). Estruturas de Dados e Seus
Algoritmos. 3. Edio. LTC.
ZIVIANI N. (2005). Projeto de Algoritmos com implementaes em Pas-
cal e C, 2da. Edio. Thomson.

Mariela Ins Corts


doutora em Informtica pela Pontifcia Universidade Catlica do Rio
de Janeiro (2003) e mestre em Sistemas de Computao pelo Intituto Militar
de Engenharia do Rio de Janeiro (1999). Sua alma mater a Universidade
Nacional de La Plata, onde completou os estudos de graduao em Cincias
da Computao. Especialista na rea de Engenharia de Software, atual-
mente professora adjunta na Universidade Estadual do Cear, vinculada
ao Curso de Cincias da Computao, onde ministra dentre outras, a dis-
ciplina de Estrutura de Dados. Adicionalmente, coordena o Laboratrio de
Qualidade e Padres de Software (LAPAQ) e lidera o Grupo de Engenharia
de Software e Sistemas Inteligentes (GESSI).

102 ESTRUTURA DE DADOS

Das könnte Ihnen auch gefallen