Professional Documents
Culture Documents
ACH2023 - AL GORI TM OS E
ESTRUTURAS DE DADOS I
atualizada em 03/06/2011
Esta apostila apresenta uma coletnea de algoritmos sobre uma variedade de estruturas de dados de memria
principal estudadas na disciplina ACH2023 Algoritmos e Estruturas de Dados I, a saber:
Listas Lineares
Sequenciais
Ligadas
Implementao Esttica
Implementao Dinmica
Tcnicas Especiais: Cabea, Sentinela, Circularidade, Encadeamento Duplo
Filas
Implementao Esttica
Implementao Dinmica
Deques (Filas de duas Pontas)
Implementao Dinmica
Pilhas
Implementao Esttica
Implementao Dinmica
Implementao de Mltiplas Pilhas em um Vetor
Aplicaes
Matrizes Esparsas
Listas Generalizadas
Listas no Lineares
rvores Binrias
rvores de Busca Binria
rvores AVL
A forma mais comum de implementao de uma lista sequencial atravs de um vetor de elementos (A) do
tipo REGISTRO de tamanho mximo possvel definido pela constante MAX.
Os registros contm campos de informaes variadas que so dependentes da aplicao. Por exemplo, um
registro de aluno conteria campos como nome, idade, NroUSP etc. Para efeito de demonstrao da busca em
estruturas ordenadas e outras operaes de identificao de elementos, definimos tambm um campo chave
em cada registro.
Vantagens:
Acesso direto a qualquer elemento com base no seu ndice. O tempo constante O(1). No entanto, em
muitas aplicaes o ndice do dado procurado no conhecido, o que faz desta uma vantagem apenas
relativa.
Se a lista estiver ordenada pela chave em questo, a busca por uma chave pode ser efetuada atravs de
busca binria O(lg n), que excelente.
Desvantagens:
Mesmo em uma estrutura ordenada, o pior caso de insero e excluso (na frente da lista) exige
movimentao de todos os n elementos da lista, ou seja, O(n). Isso pode ser inadequado para aplicaes em
que ocorrem muitas atualizaes, e principalmente por causa disso que a lista sequencial muitas vezes
substituda por uma estrutura de dados mais complexa.
Implementao esttica, exigindo que o tamanho do vetor seja previamente estabelecido. Embora
algumas linguagens de programao (como C) permitam a expanso posterior de um vetor deste tipo, esta
operao requer cpia de reas de dados inteiras em memria, a um custo O(n) que inviabiliza sua aplicao
no caso geral.
Se houver algum n p desregulado no caminho entre x e a raiz, este deve sofrer uma operao de rotao para
que seu equilbrio seja restaurado (e para que a rvore volte a ser AVL). A operao de rotao gira em torno
de p, e somente esta subrvore afetada.
(ou a um de seus ancestrais), temos uma de quatro operaes p ossveis, divididas em duas rotaes simples
(LL ou RR) e duas duplas (LR ou RL).
Existem muitos tipos de rvores balanceadas. Dentre as mais difundidas, e que serviram de base para vrios
outros modelos, esto as rvores balanceadas em altura, ou rvores AVL (dos criadores Adelson -Velskeii &
Landis) propostas em 1962. Uma rvore dita AVL se todos os seus ns so AVL. Um n dito AVL se as
alturas de sua subrvore direita (h D) e esquerda (h E) no diferem em mais de uma unidade em mdulo, ou
seja:
| hD hE | < = 1
A diferena entre a altura da subrvore direita e esquerda chamada fator de b alanceamento do n AVL.
Como o custo de clculo deste fator computacionalmente elevado, em geral o n possui um campo para
armazenar este tipo de informao, a qual deve ser atualizada pelos algoritmos de atualizao da estrutura.
A eficincia da busca em uma ABB com ou sem sentinela determinada pela altura da estrutura. Uma rvore
completa (de altura mnima da ordem lg n) permite uma busca de pior caso O(lg n), ou seja, to eficiente
quanto busca binria em vetor. Por outro lado, uma rvore assimtrica (de altura mxima da ordem n) exige
uma busca de pior caso O(n), ou seja, o mesmo que em uma lista ligada.
rvores completas so entretanto difceis de manter, ou seja, garantir que uma ABB continue sendo completa
depois de cada insero ou excluso pode exigir a movimentao de todos os ns da estrutura em tempo O(n),
ou seja, o mesmo problema que era verificado em listas sequenciais (vetores). No exemplo a seguir a insero
da chave 0 demonstra porque restaurar a condio de rvore completa invivel na prt ica.
Cada registro contm, alm dos campos exigidos pela aplicao, um campo prox que contm um ndice para
o prximo elemento na srie (vazio ou ocupado, conforme descrito a seguir). Um campo prox com valor -1
ser usado para designar que o elemento em questo no possui sucessor.
Ao ser criada, a lista possui inicio = -1 (que indica que a lista est vazia) e dispo = 0 (ou seja, a primeira
Na excluso de uma chave em uma rvore de busca binria h 3 casos a tratar: posio do vetor est disponvel). Alm disso, os campos prox de cada registro (exceto o ltimo) apontam
1. o n a excluir no possui filhos; neste caso basta desalocar a memria e atualizar o ponteiro do n pai. para o registro seguinte, constituindo uma lista de registros vazios encabeada por dispo. O campo prox do
2. o n a excluir possui apenas um filho (direito ou esquerdo): neste caso o filho passa a ocupar a posio do ltimo registro recebe o valor -1 indicando que no h mais elementos depois daquele ponto.
n excludo.
3. o n a excluir possui os dois filhos: neste caso a chave a ser excluda substituda pela chave do maior A lista est cheia quando no h mais ns disponveis (i.e., quando disp o == -1). A lista esta vazia quando
descendente esquerda, ou pela chave do menor descendente direito do n em questo. Depois disso, este no h elemento inicial (i.e., quando inicio == -1).
n descendente cuja chave for promovida posio do n excludo excludo segundo o caso 1 ou 2
acima, j que ele prprio pode ter no mximo um filho (se tivesse dois filhos no poderia ser o maior
descendente esquerdo ou menor descendente direito).
Para evitar a necessidade de definio antecipada do tamanho mximo da estrutura de implementao esttica
(i.e., o vetor), podemos tirar proveito dos recursos de alocao dinmica de memria das linguagens de
programao como C, deixando o gerenciamento de ns livres / ocupados a cargo do ambiente de
programao. Esta tcnica constitui implementao dinmica de listas ligadas, e requer o uso das funes
disponibilizadas em :
Em uma lista ligada de implementao dinmica, no h mais uso de vetores. Cada elemento da lista uma
estrutura do tipo NO, que contm os dados de cada elemento (inclusive a chave) e um ponteiro pr ox para o
prximo n da lista. Um nome auxiliar (estrutura) usado para permitir a auto-referncia ao tipo NO que est
sendo definido.
Em altura: DGHFBECA
Em nvel: ABCDEFGH
Os algoritmos para estes percursos no so recursivos. O percurso em nvel, por exemplo, mais facilmente
obtido com uma estrutura auxiliar do tipo fila, usada para armazenar os filhos de cada n visitado e ento
O tipo LISTA propriamente dito simplesmente um ponteiro inicio apontando para o primeiro n da visit-los na ordem em que so retirados da mesma.
estrutura (ou para NULL no caso da lista vazia). O ltimo elemento da lista possui seu ponteiro prox tambm
apontando para NULL. Embora no seja necessrio o encapsulamento deste ponteiro em um tipo LISTA
(afinal, uma lista apenas um ponteiro, que pode ser NULL ou no), esta medida ser adotada aqui por
questes de padronizao em relao aos tipos LISTA anteriores, e tambm porque alguns dos prximos
tipos agregaro mais informaes a esta definio.
A alocao e desalocao de ns feita dinamicamente pelo prprio compilador C atravs das primitivas
malloc e free, respectivamente.
Via de regra, malloc() usado em rotinas de insero ou criao de novos ns, enquanto que free() usado na
excluso. Rotinas que no criam ou destroem ns dificilmente precisam usar estas funes.
A nica diferena significativa entre as implementaes esttica e dinmica de listas ligadas est no fato de
e nos obriga a gerenciar as posies livres e
Os percursos bsicos em rvore binria so facilmente obtidos com uma implementao recursiva.
Embora a implementao dinmica seja mais comum, rvores binrias podem ser representadas em um vetor.
Isso especialmente til em aplicaes que no sofrem grande volume de inseres e excluses; nos demais
casos a representao dinmica continua sendo a preferida.
Na representao esttica, o vetor deve ser grande o suficiente para conter o nmero mximo possvel de ns
para a altura mxima h max estabelecida, ou seja, deve ter no mnimo 2hmax 1 posies. Isso necessrio
porque mesmo os ns no existentes tero seu espao reservado no vetor, j que a posio relativa de
qualquer pai ou filho no vetor fixa, definida em funo das posies de seus antecessores.
Os ns da rvore so dispostos ao longo do vetor em nveis, da esquerda para a direita, comeando pela raiz
(que ocupa a primeira posio). Como os ns inexistentes deixam posies vazias no vetor, algum tipo de
controle deve ser feito para diferenciar posies livres e ocupadas (e.g., com uso de um campo booleano).
Uma vez que a raiz ocupa a primeira posio do vetor, os outros ns tm suas posies definidas como segue:
I mplementao Dinmica
O n cabea, criado no incio de uma lista, usado para simplificar o projeto dos algoritmos de insero e
excluso. Pode tambm armazenar a chave de busca (funcionando como n sentinela) quando a lista for
circular.
A circularidade em geral exigncia da aplicao (e.g., que precisa percorrer continuamente a estrutura) mas
pode tambm facilitar inseres e excluses quando combinada com uso de um n cabea.
Pr opr iedades
i-1
- O nmero mximo de ns possveis no nvel i 2
Quando necessitamos percorrer a lista indistintamente em ambas as direes, usamos encadeamento duplo
(ligando cada n ao seu antecessor e ao seu sucessor).
Quando existe mais de um caminho possveis pela estrutura, esta dita no linear. Exemplos clssicos de
estruturas deste tipo so as rvores e grafos (estes estudados em Algoritmos e Estruturas de Dados II).
3.1. r vor es
Uma rvore um conjunto de ns composto de um n especial (chamado raiz) e conjuntos disjuntos de ns
subordinados ao n raiz que so eles prprios (sub)rvores.
Ter minologia
Uma rvore de grau m dita m-ria. rvores m-rias so de difcil representao e manipulao (por
exemplo, a definio de muitos ponteiros em cada n representa um grande desperdcio de espao ocupado
por ponteiros NULL). Por este motivo, rvores m-rias so geralmente representadas por rvores binrias
(veja definio a seguir) sem perda de propriedades.
Em computao, rvores (e especialmente rvores binrias) so usadas para armazenar dados (chaves e outros
campos de informao) em seus ns da mesma forma que listas sequenciais e listas ligadas.
Uma rvore binria uma estrutura vazia ou um n raiz e duas subrvores chamadas esquerda e direita, as
quais so tambm rvores binrias (vazias ou no). importante observar que uma rvore binria no
apenas uma rvore de grau mximo dois, pois h tambm a questo de ordem (esquerda e direita) de
subrvores, conceito este que no existe na definio de rvore comum discutida no item anterior.
Uma vez que rvores m-rias no definem uma ordem especfica entre as subrvores de cada n, a converso
de rvore m-ria para binria trivial: basta eleger um filho qualquer como raiz da subrvore esquerda, e os
demais como subrvore direita e seus descendentes. O procedimento de converso compreende dois passos:
A rvore assim resultante pode ser redesenhada na posio correta (preservando-se as ligaes esquerda e
direita estabelecidas) formando uma rvore binria.
O comportamento de fila obtido armazenando -se a posio das extremidades da estrutura (chamadas aqui
de fim e incio), e permitindo entrada
A implementao pode ser esttica (usando um vetor circular) ou dinmica (com ponteiros) sem diferenas
significativas em termos de eficincia, uma vez que estas operaes s podem ocorrer nas extremidades da
estrutura.
Deques so filas que permitem tanto entrada quanto retirada em ambas extremidades. Neste caso no faz mais
sentido falar em incio e fim de fila, mas simplesmente incio1 e incio2.
Implementaes estticas e dinmicas so possveis, mas a dinmica mais comum, tirando proveito do
encadeamento duplo para permitir acesso a ambas extremidades em tempo O(1).
Se a matriz possui no-nulos distribudos de forma regular (e.g., em torno da diagonal principal) mais
conveniente elaborar uma frmula de endereamento para estes dados e mant -los em um vetor V de n
posies, onde n a quantidade de no-nulos a armazenar.
A pilha armazena apenas a posio de uma de suas extremidades (chamada topo), que o nico local onde
so realizadas todas as operaes de entrada e sada. A operao de entrada de dados (sempre no topo da
pilha ) chamada push e a retirada (tambm sempre do topo) chamada pop.
A implementao pode ser esttica (usando um vetor simples) ou dinmica (com ponteiros) sem diferenas
significativas em termos de eficincia, uma vez que a estrutura s admite estas operaes no topo da
estrutura.
Para uma matriz de MAXLIN x MAXCOL elementos, dos quais n so no-nulos, a representao por listas
cruzadas ser vantajosa (do ponto de vista da complexidade de espao) sempre que:
Por outro lado, a representao por linhas no apresenta bom tempo de resposta para certas operaes
matriciais. Em especial, percorrer uma linha da matriz exige que todas as linhas acima dela sejam percorridas.
2.5.3. Repr esentao de duas pilhas em um nico vetor Pior do que isso, percorrer uma coluna da matriz exige que a matriz inteira (ou melhor, todos os seus
elementos no-nulos) seja percorrida. Considerando-se que matrizes esparsas tendem a ser estruturas de
Duas pilhas de implementao esttica que no necessitam de toda sua capacidade simultaneamente podem grande porte, em muitas aplicaes estes tempos de execuo podem ser inaceitveis.
ser representadas economicamente em um nico vetor compartilhado.
2.6.2. Repr esentao por L istas Cr uzadas
As pilhas so posicionadas nas extremidades do vetor e crescem em direo ao centro. Supondo -se um vetor
com posies indexadas de 0 at MAX-1, o topo da primeira pilha inicializado com -1 e o topo da segunda Com um gasto adicional de espao de armazenamento, podemos representar uma matriz esparsa com tempo
inicializado com MAX, correspondendo as situaes de pilha vazia de cada estrutura. As duas pilhas esto de acesso proporcional ao volume de dados de cada linha ou coluna. Nesta representao, usamos uma lista
simultaneamente cheias quando no h mais posies livres entre elas, ou seja, quando (topo2 - topo1 == 1). ligada para cada linha e outra para cada coluna da matriz. As listas se cruzam, isto , compartilham os
mesmos ns em cada interseco, e por este motivo cada n armazena um ponteiro para a prxima linha
(abaixo) e prxima coluna ( direita).
1 2 3 4 5 6 7 8
2 A B
3
4 C
5 D
6 E F G H
7
Uma matriz esparsa uma matriz extensa na qual poucos elementos so no -nulos (ou de valor diferente de
zero). O problema de representao destas estruturas consiste em economizar memria armazenando apenas
os dados vlidos (i.e., no nulos) sem perda das propriedades matriciais (i.e., a noo de posio em linha e
coluna de cada elemento). As implementaes mais comuns so a representao em linhas ou por listas
cruzadas.
A forma mais simples (porm no necessariamente mais eficiente) de armazenar uma matriz esparsa na
forma de uma tabela (na verdade, uma lista ligada) de ns contendo a linha e coluna de cada elemento e suas
demais informaes. A lista ordenada por linhas para facilitar o percurso neste sentido.
A matriz ser acessvel a partir do ponteiro de incio da lista ligada que a representa.
O caso geral de representao esttica de 'NP' pilhas compartilhando um nico vetor envolve o controle
individual do topo de cada pilha e tambm da sua base. Cada topo [k] aponta pa ra o ltimo elemento efetivo
de cada pilha (i.e., da mesma forma que o topo de uma pilha comum) mas, para que seja possvel diferenciar
uma pilha vazia de uma pilha unitria, cada base [k] aponta para o elemento anterior ao primeiro elemento
real da respectiva pilha.
Uma pilha k est vazia se base[k] == topo[k]. Uma pilha [k] est cheia se topo[k] == base[k+1], significando
que a pilha [k] no pode mais crescer sem sobrepor-se a pilha [k+1].
Na inicializao da estrutura, cada topo igualado a sua respectiva base, o que define uma pilha vazia. Alm
disso, para evitar acmulo de pilhas em um mesmo ponto do vetor (o que ocasionaria grande movimentao
de dados nas primeiras entradas de dados), todas as NP+1 pilhas so inicializadas com suas bases distribudas
a intervalos regulares ao longo da estrutura.
A incluso de um novo elemento no topo de uma pilha k deve considerar a existncia de espao livre e, se for
A pilha[0] fica na posio 1. A pilha[NP] - que apenas um artifcio de programao - fica o caso, movimentar as estruturas vizinhas para obt-lo. No exemplo a seguir, o programa tenta deslocar todas
permanentemente na posio MAX-1, servindo apenas como marcador de fim do vetor (i.e., esta pilha jamais as pilhas direita de k em uma posio para a direita. Se isso falhar, tenta deslocar todas as pilhas da
ser afetada pelas rotinas de deslocamento). A pilha extra ser sempre vazia e ser usada para simplificar o esquerda (inclusive k) uma posio para a esquerda. Se isso ainda no resultar em uma posio livre no topo
teste de pilha cheia, que pode se basear sempre na comparao entre um topo e a base da pilha seguinte, ao de k, ento o vetor est totalmente ocupado e a insero no pode ser realizada.
invs de se preocupar tambm com o fim do vetor.
Observe que este apenas um exemplo de estratgia possvel. Um procedimento talvez mais eficiente poderia
tentar primeiro deslocar apenas a pilha k+1 para direita. Apenas quando isso falhasse poderia ento tentar
deslocar apenas as pilha k-1 e a pilha k para a esquerda, e s em caso de ltima necessidade tentaria
o caso especial em que k a ltima pilha real (i.e., quando k == NP-1). deslocaria vrias pilhas simultaneamente como feito acima.