27.11.2014 Views

LISTAS LINEARES - Universidade Estadual de Mato Grosso do Sul

LISTAS LINEARES - Universidade Estadual de Mato Grosso do Sul

LISTAS LINEARES - Universidade Estadual de Mato Grosso do Sul

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

<strong>Universida<strong>de</strong></strong> <strong>Estadual</strong> <strong>de</strong> <strong>Mato</strong> <strong>Grosso</strong> <strong>do</strong> <strong>Sul</strong> - Curso <strong>de</strong> Ciência da Computação<br />

Disciplina: Estruturas <strong>de</strong> Da<strong>do</strong>s<br />

Profª. Raquel Marcia Müller<br />

1<br />

Listas Lineares<br />

Dentre as estruturas <strong>de</strong> da<strong>do</strong>s não primitivas, as listas lineares são as <strong>de</strong><br />

manipulação mais simples.<br />

Uma lista linear agrupa informações referentes a um conjunto <strong>de</strong> elementos<br />

que, <strong>de</strong> alguma forma, se relacionam entre si. Ela po<strong>de</strong> se constituir, por exemplo, <strong>de</strong><br />

informações sobre os funcionários <strong>de</strong> uma empresa, sobre notas <strong>de</strong> compras, itens <strong>de</strong><br />

estoque, notas <strong>de</strong> alunos, etc.<br />

Uma lista linear, ou tabela, é então um conjunto <strong>de</strong> n ≥ 0 nós L[1], L[2], ...,<br />

L[n] tais que suas proprieda<strong>de</strong>s estruturais <strong>de</strong>correm, unicamente, da posição relativa<br />

<strong>do</strong>s nós <strong>de</strong>ntro da seqüência linear. Tem-se:<br />

• se n > 0, L[1] é o primeiro nó;<br />

• para 1 < K ≤ n, o nó L[k] é precedi<strong>do</strong> por L[k-1];<br />

• Operações Mais Freqüentes Em Listas:<br />

• busca;<br />

• inclusão;<br />

• remoção;<br />

São operações básicas, que precisam <strong>de</strong> algoritmos eficientes.<br />

• Outras Operações:<br />

• alteração;<br />

• combinação <strong>de</strong> duas listas;<br />

• or<strong>de</strong>nação;<br />

• <strong>de</strong>terminação <strong>do</strong> primeiro e <strong>do</strong> último nó da lista.<br />

• Casos Particulares <strong>de</strong> Lista:<br />

• <strong>de</strong>que (inserção e remoção só nas extremida<strong>de</strong>s da lista);<br />

• pilha (inserção e remoção só em um extremo);<br />

• pilha( inserção em um extremo e remoções no outro).<br />

• Tipo <strong>de</strong> armazenamento <strong>de</strong> uma lista:<br />

• alocação seqüencial;<br />

• alocação enca<strong>de</strong>ada.<br />

Alocação Seqüencial<br />

Maneira mais simples <strong>de</strong> se manter uma lista na memória. Como a<br />

implementação <strong>de</strong> alocação seqüencial em linguagens <strong>de</strong> alto nível é geralmente<br />

realizada com reserva <strong>de</strong> memória ⇒ alocação estática.<br />

Obs.: Inserção e Remoção <strong>de</strong> nós não ocorrem <strong>de</strong> fato: simulação.<br />

I<strong>de</strong>al para filas e pilhas.<br />

Seja uma lista linear. Cada nó é forma<strong>do</strong> por campos, que armazenam as<br />

características distintas <strong>do</strong>s elementos da lista. Além disso, cada nó da lista possui,<br />

geralmente, um i<strong>de</strong>ntifica<strong>do</strong>r, <strong>de</strong>nomina<strong>do</strong> chave. Para evitar ambigüida<strong>de</strong>s, supõe-se


<strong>Universida<strong>de</strong></strong> <strong>Estadual</strong> <strong>de</strong> <strong>Mato</strong> <strong>Grosso</strong> <strong>do</strong> <strong>Sul</strong> - Curso <strong>de</strong> Ciência da Computação<br />

Disciplina: Estruturas <strong>de</strong> Da<strong>do</strong>s<br />

Profª. Raquel Marcia Müller<br />

2<br />

que todas as chaves são distintas. A chave, quan<strong>do</strong> presente, se constitui em um <strong>do</strong>s<br />

campos <strong>do</strong> nó. Os nós po<strong>de</strong>m se encontrar or<strong>de</strong>na<strong>do</strong>s, ou não, segun<strong>do</strong> os valores <strong>de</strong><br />

suas chaves ⇒ lista or<strong>de</strong>nada ou não-or<strong>de</strong>nada.<br />

Ex. 1: Consi<strong>de</strong>re uma lista L <strong>de</strong> n elementos.<br />

Nó 1 Nó 2 Nó 3 Nó 4 Nó 5<br />

Chave Nome En<strong>de</strong>reço<br />

⇒ REGISTRO<br />

Ex.1.1: Algoritmo que realiza a busca <strong>de</strong> um elemento na lista L.<br />

Função busca (x); {x é o elemento procura<strong>do</strong>}<br />

inicio<br />

i ← 1;<br />

busca ← 0;<br />

enquanto i ≤ n faça<br />

se L[i].chave = x então {chave encontrada}<br />

busca ← i;<br />

i ← n +1;<br />

senão<br />

i ← i + 1;<br />

{pesquisa prossegue}<br />

fim se<br />

fim enquanto<br />

fim;<br />

Ex.1.1a: Outra maneira <strong>de</strong> escrever o algoritmo:<br />

Função busca (x); {x é o elemento procura<strong>do</strong>}<br />

inicio<br />

L[n+1].chave ← x;<br />

enquanto L[i].chave ≠ x faça<br />

i ← i + 1;<br />

fim enquanto<br />

se i ≠ n + 1 então<br />

busca ← i;<br />

senão<br />

busca ← 0;<br />

fim se<br />

fim;


<strong>Universida<strong>de</strong></strong> <strong>Estadual</strong> <strong>de</strong> <strong>Mato</strong> <strong>Grosso</strong> <strong>do</strong> <strong>Sul</strong> - Curso <strong>de</strong> Ciência da Computação<br />

Disciplina: Estruturas <strong>de</strong> Da<strong>do</strong>s<br />

Profª. Raquel Marcia Müller<br />

3<br />

Ex.2: Algoritmo para busca na lista or<strong>de</strong>nada:<br />

Função busca_ord (x); {x é o elemento procura<strong>do</strong>}<br />

inicio<br />

L[n+1].chave ← x;<br />

enquanto L[i].chave ≠ x faça<br />

i ← i + 1;<br />

fim enquanto<br />

se i ≠ n + 1 ou L[i].chave ≠ x então<br />

busca_ord ← 0;<br />

senão<br />

busca_ord ← i;<br />

fim se<br />

fim;<br />

Ex.3: Um méto<strong>do</strong> bem mais eficiente: Busca Binária.<br />

Função busca_binaria (x); {x é o elemento procura<strong>do</strong>}<br />

inicio<br />

inf ← 1;<br />

sup ← n;<br />

busca_binaria ← 0;<br />

enquanto inf ≤ sup faça<br />

meio ← L[inf + sup)/2]; {índice a ser busca<strong>do</strong>}<br />

se L[meio].chave = x então<br />

busca_binaria ← meio; {elemento encontra<strong>do</strong>}<br />

inf ← sup + 1;<br />

senão<br />

se L[meio].chave < x então<br />

inf ← meio + 1;<br />

senão<br />

sup ← meio -1;<br />

fim se<br />

fim se<br />

fim enquanto<br />

fim;<br />

Para realizar as operações <strong>de</strong> inserção e remoção utilizamos o procedimento <strong>de</strong><br />

busca. No caso da inserção, o objetivo é evitar chaves repetidas e, no caso da remoção, a<br />

necessida<strong>de</strong> <strong>de</strong> localizar o elemento a ser removi<strong>do</strong>.


<strong>Universida<strong>de</strong></strong> <strong>Estadual</strong> <strong>de</strong> <strong>Mato</strong> <strong>Grosso</strong> <strong>do</strong> <strong>Sul</strong> - Curso <strong>de</strong> Ciência da Computação<br />

Disciplina: Estruturas <strong>de</strong> Da<strong>do</strong>s<br />

Profª. Raquel Marcia Müller<br />

4<br />

Ex:4: O algoritmo abaixo efetua a inserção <strong>de</strong> um nó na lista.<br />

Algoritmo {inserção <strong>de</strong> um nó na lista L}<br />

se n < m então<br />

se busca(x) = 0 então<br />

L[n+1] ← novo_valor;<br />

n ← n + 1;<br />

senão<br />

escreva (“elemento já existe na tabela”);<br />

fim se<br />

senão<br />

escreva (“overflow”);<br />

fim se<br />

Fim algoritmo<br />

Ex 5: O algoritmo abaixo efetua a remoção <strong>de</strong> um nó da lista.<br />

Algoritmo {remoção <strong>de</strong> um nó na lista L}<br />

se n ≠ 0 então<br />

índice ← busca(x);<br />

se índice = 0 então<br />

valor_recupera<strong>do</strong> ← L[índice];<br />

para i <strong>de</strong> 1 até n – 1 faça<br />

L[i] ← L[i+1];<br />

fim para<br />

n ← n – 1;<br />

senão<br />

escreva (“elemento não se encontra na tabela”);<br />

fim se<br />

senão<br />

escreva (“un<strong>de</strong>rflow”);<br />

fim se<br />

fim algoritmo<br />

Ambos os algoritmos consi<strong>de</strong>ram tabelas não or<strong>de</strong>nadas. A memória<br />

pressuposta disponível tem m posições (na realida<strong>de</strong> m+1, porque é necessária uma<br />

posição extra para a busca).<br />

• Overflow: não há mais espaço para inserção;<br />

• Undrflow: remoção em lista vazia.<br />

Obs.: Ambos os casos fazer tratamento<br />

No caso <strong>de</strong> tabelas or<strong>de</strong>nadas, o algoritmo <strong>de</strong> remoção não se modifica. O<br />

algoritmo <strong>de</strong> inserção, entretanto, precisa ser refeito, uma vez que, nesse caso, a posição<br />

<strong>do</strong> nó torna-se relevante.


<strong>Universida<strong>de</strong></strong> <strong>Estadual</strong> <strong>de</strong> <strong>Mato</strong> <strong>Grosso</strong> <strong>do</strong> <strong>Sul</strong> - Curso <strong>de</strong> Ciência da Computação<br />

Disciplina: Estruturas <strong>de</strong> Da<strong>do</strong>s<br />

Profª. Raquel Marcia Müller<br />

5<br />

Pilhas e Filas<br />

Armazenamento seqüencial ⇒ i<strong>de</strong>al quan<strong>do</strong> inserções e remoções não<br />

acarretam movimentação <strong>de</strong> nós, o que ocorre se os elementos a serem inseri<strong>do</strong>s e<br />

removi<strong>do</strong>s estão em posições seqüenciais, como a primeira ou a última posição. Pilhas e<br />

filas satisfazem tais condições.<br />

Pilhas<br />

Utiliza-se indica<strong>do</strong>res especiais, <strong>de</strong>nomina<strong>do</strong>s ponteiros, para o acesso a<br />

posição selecionadas. No caso da pilha, usa-se apenas um ponteiro, o ponteiro topo, pois<br />

as inserções e remoções são executadas na mesma extremida<strong>de</strong> da lista.<br />

Ex1.: Pilha<br />

Situação 1: inicial: pilha vazia<br />

1 2 3 . . . m<br />

⇑<br />

topo<br />

Situação 2: inserir informação A<br />

1 2 3 . . . m<br />

A<br />

⇑<br />

topo<br />

Situação 3: inserir informação B<br />

1 2 3 . . . m<br />

A<br />

B<br />

Situação 4: retirar informação B<br />

1 2 3 . . . m<br />

A<br />

⇑<br />

topo<br />

Situação 5: inserir informação C<br />

1 2 3 . . . m<br />

A<br />

⇑<br />

topo<br />

C<br />

⇑<br />

topo


<strong>Universida<strong>de</strong></strong> <strong>Estadual</strong> <strong>de</strong> <strong>Mato</strong> <strong>Grosso</strong> <strong>do</strong> <strong>Sul</strong> - Curso <strong>de</strong> Ciência da Computação<br />

Disciplina: Estruturas <strong>de</strong> Da<strong>do</strong>s<br />

Profª. Raquel Marcia Müller<br />

6<br />

Situação 6: retirar informação C<br />

1 2 3 . . . m<br />

A<br />

⇑<br />

topo<br />

Situação 7: retirar informação A<br />

1 2 3 . . . m<br />

⇑<br />

topo<br />

pilha vazia<br />

Ex.1a: Algoritmo <strong>de</strong> inserção na pilha P<br />

Algoritmo<br />

se topo ≠ M então<br />

topo ← topo + 1;<br />

P [topo] ← novo_valor;<br />

senão<br />

escreva(“overflow”);<br />

fim se<br />

Fim Algoritmo<br />

Ex. 1b: Algoritmo <strong>de</strong> remoção da pilha P<br />

Algoritmo<br />

se topo ≠ 0 então<br />

valor_recupera<strong>do</strong> ← P [topo];<br />

topo ← topo - 1;<br />

senão<br />

escreva(“un<strong>de</strong>rflow”);<br />

fim se<br />

Fim Algoritmo<br />

Filas<br />

Filas exigem uma implementação mais elaborada. São necessários <strong>do</strong>is<br />

ponteiros: início da fila (I) e retaguarda (R). Isso porque na fila as inserções são feitas<br />

sempre no final da fila e as remoções sempre no início da fila. Para a inserção <strong>de</strong> um<br />

elemento, move-se o ponteiro R; para a retirada, move-se o ponteiro I. A fila vazia é<br />

representada por I = R = 0.


<strong>Universida<strong>de</strong></strong> <strong>Estadual</strong> <strong>de</strong> <strong>Mato</strong> <strong>Grosso</strong> <strong>do</strong> <strong>Sul</strong> - Curso <strong>de</strong> Ciência da Computação<br />

Disciplina: Estruturas <strong>de</strong> Da<strong>do</strong>s<br />

Profª. Raquel Marcia Müller<br />

7<br />

Ex2.: Fila<br />

Situação 1: inicial: fila vazia<br />

1 2 3 . . . m<br />

⇑<br />

I R<br />

Situação 2: inserir informação A<br />

1 2 3 . . . m<br />

A<br />

⇑<br />

I R<br />

Situação 3: inserir informação B<br />

1 2 3 . . . m<br />

A B<br />

⇑<br />

I<br />

⇑<br />

R<br />

Situação 4: retirar informação A<br />

1 2 3 . . . m<br />

B<br />

⇑<br />

I R<br />

Situação 5: inserir informação C<br />

1 2 3 . . . m<br />

B C<br />

⇑<br />

I<br />

⇑<br />

R<br />

Situação 6: retirar informação B<br />

1 2 3 . . . m<br />

C<br />

⇑<br />

I R


<strong>Universida<strong>de</strong></strong> <strong>Estadual</strong> <strong>de</strong> <strong>Mato</strong> <strong>Grosso</strong> <strong>do</strong> <strong>Sul</strong> - Curso <strong>de</strong> Ciência da Computação<br />

Disciplina: Estruturas <strong>de</strong> Da<strong>do</strong>s<br />

Profª. Raquel Marcia Müller<br />

8<br />

Situação 7: retirar informação C<br />

1 2 3 . . . m<br />

⇑<br />

topo<br />

fila vazia<br />

Ex: 2a: Algoritmo <strong>de</strong> inserção da fila F<br />

Algoritmo<br />

inicio<br />

prov ← r mod M+1;<br />

se prov ≠ I então<br />

r ← prov;<br />

F[r] ← novo_valor;<br />

se I = 0 então<br />

I ← 1;<br />

fim se<br />

senão<br />

escreva (“overflow”);<br />

fim se<br />

Fim Algoritmo<br />

Ex: 2b: Algoritmo <strong>de</strong> remoção da fila F<br />

Algoritmo<br />

inicio<br />

se I ≠ 0 então<br />

valor_recupera<strong>do</strong> ← F[I];<br />

se I = R então<br />

I ← R ← 0;<br />

senão<br />

I ← I mod n + 1;<br />

fim se<br />

senão<br />

escreva (“un<strong>de</strong>rflow”);<br />

fim se<br />

Fim Algoritmo<br />

À medida que os ponteiros são incrementa<strong>do</strong>s na memória disponível, a fila<br />

“se move”, o que po<strong>de</strong> dar origem à falsa impressão <strong>de</strong> memória esgotada. Para eliminar<br />

esse problema, consi<strong>de</strong>ram-se os m nós aloca<strong>do</strong>s como se estivessem em círculo, on<strong>de</strong><br />

F[1] segue F[m].<br />

Notação Polonesa: Aplicação Para Pilhas<br />

Uma representação para expressões aritméticas que seja conveniente <strong>do</strong> ponto <strong>de</strong><br />

vista computacional, é aumento <strong>de</strong> interesse, por exemplo, na área <strong>de</strong> compila<strong>do</strong>res. A


<strong>Universida<strong>de</strong></strong> <strong>Estadual</strong> <strong>de</strong> <strong>Mato</strong> <strong>Grosso</strong> <strong>do</strong> <strong>Sul</strong> - Curso <strong>de</strong> Ciência da Computação<br />

Disciplina: Estruturas <strong>de</strong> Da<strong>do</strong>s<br />

Profª. Raquel Marcia Müller<br />

9<br />

notação tradicional é ambígua e, portanto, obriga ao pre-estabelecimento <strong>de</strong> regras <strong>de</strong><br />

priorida<strong>de</strong>, o que torna a tarefa computacional mais complexa,<br />

Consi<strong>de</strong>ran<strong>do</strong> apenas operações binárias, temos outros tipos <strong>de</strong> representação:<br />

• notação completamente parentizada: acrescenta-se sempre um para <strong>de</strong><br />

parênteses a cada par <strong>de</strong> operan<strong>do</strong>s e a seu opera<strong>do</strong>r.<br />

EX:<br />

notação tradicional: A * B – C / D<br />

notação parentizada: ((A * B) – (C/D))<br />

• notação polonesa: os operan<strong>do</strong>s aparecem imediatamente antes <strong>do</strong>s<br />

operan<strong>do</strong>s. Essa notação explicita quais operan<strong>do</strong>s, e em que or<strong>de</strong>m, <strong>de</strong>vem ser<br />

calcula<strong>do</strong>s. Por esse motivo, dispensa o uso <strong>de</strong> parênteses, sem ambigüida<strong>de</strong>s.<br />

EX:<br />

notação tradicional: A * B – C / D<br />

notação polonesa: -* A B / C D<br />

• notação polonesa reversa: notação polonesa com os opera<strong>do</strong>res<br />

aparecen<strong>do</strong> após os operan<strong>do</strong>s. (usada em máquinas <strong>de</strong> calcular).<br />

EX:<br />

notação tradicional: A * B – C / D<br />

notação polonesa: A B * C D / -<br />

Tanto a expressão original quanto a expressão resultante <strong>de</strong>vem ser<br />

armazenadas em listas.<br />

⇒ Antes <strong>de</strong> colocar o algoritmo, exemplificar.<br />

Expressão parentizada: ((3*4) – (10/2))


<strong>Universida<strong>de</strong></strong> <strong>Estadual</strong> <strong>de</strong> <strong>Mato</strong> <strong>Grosso</strong> <strong>do</strong> <strong>Sul</strong> - Curso <strong>de</strong> Ciência da Computação<br />

Disciplina: Estruturas <strong>de</strong> Da<strong>do</strong>s<br />

Profª. Raquel Marcia Müller<br />

10<br />

Algoritmo Para Conversão da Notação Parentizada na Notação Polonesa Reversa:<br />

• os operan<strong>do</strong>s aparecem na mesma or<strong>de</strong>m na notação tradicional e na notação<br />

polonesa reversa.<br />

Na notação polonesa reversa<br />

• na notação polonesa reversa os operan<strong>do</strong>s aparecem na or<strong>de</strong>m em que <strong>de</strong>vem ser<br />

calcula<strong>do</strong>s (da esquerda para a direita);<br />

• o operan<strong>do</strong>s aparecem imediatamente <strong>de</strong>pois <strong>de</strong> seus operan<strong>do</strong>s.<br />

A principal preocupação <strong>do</strong> algoritmo <strong>de</strong>ve ser a or<strong>de</strong>m e a posição <strong>do</strong>s<br />

opera<strong>do</strong>res. Na notação parentizada, essa or<strong>de</strong>m é indicada pelos parênteses; os mais<br />

internos significam operações prioritárias.<br />

Ex: 1: Algoritmo que realiza a conversão da notação parentizada para a polonesa<br />

reversa<br />

Algoritmo<br />

in<strong>de</strong>x ← 1; {índice da expressão parentizada}<br />

indpol ← 0; {índice da expressão polonesa}<br />

topo ← 0; {ponteiro da pilha}<br />

enquanto in<strong>de</strong>xp ≤ fim então<br />

se exp[in<strong>de</strong>xp] é operan<strong>do</strong> então {passa para a nova lista}<br />

indpol ← indpol +1;<br />

pol[indpol] ← exp[in<strong>de</strong>xp];<br />

senão<br />

se exp[in<strong>de</strong>xp] é opera<strong>do</strong>r então {coloca na pilha}<br />

topo ← topo + 1;<br />

pilha[topo] ← exp[in<strong>de</strong>xp];<br />

senão<br />

se exp[in<strong>de</strong>xp] = “)” então<br />

se topo ≠ 0 então {forma a operação}<br />

opera<strong>do</strong>r ← pilha[topo];<br />

topo ← topo - 1;<br />

indpol ← indpol + 1;<br />

pol[indpol] ← opera<strong>do</strong>r;<br />

senão<br />

"Expressão errada!";<br />

fim se<br />

fim se<br />

fim se<br />

fim se<br />

in<strong>de</strong>xp ← in<strong>de</strong>xp + 1;<br />

fim enquanto<br />

Fim Algoritmo<br />

Uma análise sintática prévia na expressão é pressuposta (verificar se a<br />

expressão é válida!). Para efetuar a conversão, <strong>de</strong>vem-se remover os parênteses e<br />

estabelecer a or<strong>de</strong>m conveniente <strong>de</strong> opera<strong>do</strong>res. Estes <strong>de</strong>vem ser armazena<strong>do</strong>s até que<br />

um ")" seja encontra<strong>do</strong>, o que indica que a operação mais interna, e por conseguinte a<br />

primeira a ser executada, foi <strong>de</strong>tectada. O último opera<strong>do</strong>r armazena<strong>do</strong> correspon<strong>de</strong> a<br />

essa operação. Portanto, a estrutura utilizada no armazenamento <strong>do</strong>s opera<strong>do</strong>res <strong>de</strong>ve


<strong>Universida<strong>de</strong></strong> <strong>Estadual</strong> <strong>de</strong> <strong>Mato</strong> <strong>Grosso</strong> <strong>do</strong> <strong>Sul</strong> - Curso <strong>de</strong> Ciência da Computação<br />

Disciplina: Estruturas <strong>de</strong> Da<strong>do</strong>s<br />

Profª. Raquel Marcia Müller<br />

11<br />

ser uma pilha. A expressão a ser convertida se encontra no vetor exp e o resulta<strong>do</strong> da<br />

conversão, no vetor pol. A variável fim indica a dimensão da expressão.<br />

Exercícios<br />

1. Utilizan<strong>do</strong> o algoritmo visto em sala, converta as expressões abaixo para a notação<br />

polonesa reversa:<br />

a) (((5 * 2) / 5) - (9 / 5))<br />

b) (7 - ((4 * (3 - 2)) * 2 ))<br />

c) (4 * (((3 - 8) / 4) - 5))<br />

2. Proponha um algoritmo para achar o resulta<strong>do</strong> das expressões na notação polonesa<br />

reversa.<br />

3. Use o algoritmo <strong>de</strong>senvolvi<strong>do</strong> no ítem anterior e calcule o resulta<strong>do</strong> das expressões<br />

<strong>do</strong> exercício 1.<br />

4. Proponha mudanças no algoritmo que converte expressões parentizadas para<br />

notação polonesa reversa, para tratar o opera<strong>do</strong>r unário - e números com mais <strong>de</strong> um<br />

dígito.<br />

Solução <strong>do</strong> exercício 2:<br />

indpol ← 1;<br />

topo ← 0;<br />

enquanto indpol ≤ fim faça<br />

se pol[indpol] é operan<strong>do</strong> então<br />

Push(pol[indpol]); {insere na pilha}<br />

senão se pol[indpol] é opera<strong>do</strong>r então<br />

oper1 ← pop(); {retira <strong>do</strong>is operan<strong>do</strong>s <strong>do</strong> topo da pilha}<br />

fim se<br />

fim se<br />

fim enquanto<br />

oper2 ← pop();<br />

result ← calcula_oper(oper2, oper1, pol[indpol]);<br />

push( result ); {empilha resulta<strong>do</strong> parcial}


<strong>Universida<strong>de</strong></strong> <strong>Estadual</strong> <strong>de</strong> <strong>Mato</strong> <strong>Grosso</strong> <strong>do</strong> <strong>Sul</strong> - Curso <strong>de</strong> Ciência da Computação<br />

Disciplina: Estruturas <strong>de</strong> Da<strong>do</strong>s<br />

Profª. Raquel Marcia Müller<br />

12<br />

Listas Lineares em Alocação Enca<strong>de</strong>ada<br />

- Operações em listas implementadas com alocação seqüencial são muito fracas;<br />

- Na utilização <strong>de</strong> mais <strong>de</strong> duas listas, a gerência <strong>de</strong> memória é mais complexa ⇒ usar<br />

alocação dinâmica (ou alocação enca<strong>de</strong>ada).<br />

Na alocação enca<strong>de</strong>ada, as posições <strong>de</strong> memória são alocadas (ou<br />

<strong>de</strong>salocadas) na medida em que são necessárias (ou dispensadas). Os nós <strong>de</strong> uma lista<br />

encontram-se aleatoriamente dispostos na memória e são interliga<strong>do</strong>s por ponteiros, que<br />

indicam a posição <strong>do</strong> próximo elemento da tabela.<br />

Cada nó terá, agora, um campo adicional, que conterá o en<strong>de</strong>reço <strong>do</strong><br />

próximo nó da lista.<br />

1 2 3 4 ... n<br />

Lista seqüencial:<br />

Lista enca<strong>de</strong>ada:<br />

nó 1 nó 2 nó 3 nó 4<br />

Vantagens e <strong>de</strong>svantagens <strong>do</strong>s tipos <strong>de</strong> alocação:<br />

- A alocação enca<strong>de</strong>ada é mais conveniente quan<strong>do</strong> o problema inclui o tratamento <strong>de</strong><br />

mais <strong>de</strong> uma lista;<br />

- O acesso ao k-ésimo elemento da lista é imediato na alocação seqüencial, enquanto<br />

na alocação enca<strong>de</strong>ada obriga ao percurso na lista até o elemento <strong>de</strong>seja<strong>do</strong>.<br />

Como em uma lista enca<strong>de</strong>ada os nós não estão, obrigatoriamente, em posições<br />

contíguas da memória, ao se realizar uma inserção ou remoção, há a necessida<strong>de</strong> <strong>de</strong><br />

encontrar novas posições <strong>de</strong> memória para armazenamento e liberar outras que possam<br />

ser reutilizadas posteriormente.<br />

É preciso, portanto, gerenciar a memória disponível. As linguagens<br />

geralmente possuem um módulo <strong>de</strong> gerência <strong>de</strong> memória disponível ao usuário,<br />

bastan<strong>do</strong> apenas que este se refira às rotinas internas <strong>de</strong> ocupação e <strong>de</strong>volução <strong>de</strong> nós da<br />

lista <strong>de</strong> espaço disponível. Em Pascal, as rotinas new(pt) e dispose(pt) executam essa<br />

tarefa.<br />

Nos algoritmos, usamos uma notação especial:<br />

- a indicação <strong>do</strong> en<strong>de</strong>reço <strong>de</strong> um nó, feita por um ponteiro, será<br />

representada pelo símbolo →. Cada ponteiro utiliza<strong>do</strong> é associa<strong>do</strong> a um<br />

único tipo <strong>de</strong> nó. Assim, pt→info representa o campo info <strong>do</strong> nó<br />

aponta<strong>do</strong> por pt; pt→prox representa o en<strong>de</strong>reço <strong>do</strong> campo prox<br />

aponta<strong>do</strong> por pt.<br />

pt<br />

info<br />

prox<br />


<strong>Universida<strong>de</strong></strong> <strong>Estadual</strong> <strong>de</strong> <strong>Mato</strong> <strong>Grosso</strong> <strong>do</strong> <strong>Sul</strong> - Curso <strong>de</strong> Ciência da Computação<br />

Disciplina: Estruturas <strong>de</strong> Da<strong>do</strong>s<br />

Profª. Raquel Marcia Müller<br />

13<br />

Um conjunto <strong>de</strong> nós enca<strong>de</strong>a<strong>do</strong>s formam uma tabela. A associação <strong>do</strong> ponteiro<br />

pt ao tipo <strong>de</strong> nó é <strong>de</strong>finida previamente na <strong>de</strong>claração das variáveis. Exemplo:<br />

<strong>de</strong>clare No registro (Info numérico,<br />

Prox ponteiro No);<br />

<strong>de</strong>clare Pt ponteiro No;<br />

pt<br />

infor<br />

prox<br />

infor<br />

prox<br />

nó<br />

nó<br />

Listas simplesmente enca<strong>de</strong>adas<br />

Qualquer estrutura, inclusive listas, que seja armazenada em alocação<br />

enca<strong>de</strong>ada requer o uso <strong>de</strong> um ponteiro que indique o en<strong>de</strong>reço <strong>de</strong> seu primeiro nó. O<br />

percurso <strong>de</strong> uma lista é feito, então, a partir <strong>de</strong>sse ponteiro. A idéia consiste em seguir,<br />

consecutivamente, pelos en<strong>de</strong>reços existentes no campo que indica o próximo nó<br />

(semelhante ao índice da alocação seqüencial).<br />

Algoritmo que percorre uma lista para impressão <strong>do</strong> campo info:<br />

Obs.: ptlista é o ponteiro para o primeiro nó.<br />

Algoritmo<br />

Pont ← ptlista; {pont é um ponteiro auxiliar}<br />

enquanto pont ≠ null faça {null indica o final da lista}<br />

escreva pont → info;<br />

Pont ← pont → prox;<br />

fim enquanto<br />

Fim algoritmo<br />

⇒ Fazer esquema para facilitar visualização!<br />

Algoritmo <strong>de</strong> busca: consi<strong>de</strong>rações<br />

- <strong>de</strong>ve ser eficiente;<br />

- primeira inserção e última remoção exigem testes especiais.<br />

Solução: nó-cabeça, nunca removi<strong>do</strong>, que será indica<strong>do</strong> pelo ponteiro <strong>de</strong> início da<br />

lista (esse nó terá essa utilida<strong>de</strong> específica, não conten<strong>do</strong>, portanto, informações<br />

relacionadas à tabela propriamente dita).<br />

Lista vazia:<br />

ptlista<br />

nó-cabeça<br />

ptlista<br />

nó 1 nó 2 nó 3


<strong>Universida<strong>de</strong></strong> <strong>Estadual</strong> <strong>de</strong> <strong>Mato</strong> <strong>Grosso</strong> <strong>do</strong> <strong>Sul</strong> - Curso <strong>de</strong> Ciência da Computação<br />

Disciplina: Estruturas <strong>de</strong> Da<strong>do</strong>s<br />

Profª. Raquel Marcia Müller<br />

14<br />

Algoritmo <strong>de</strong> busca:<br />

- ptlista: guarda o nó cabeça da lista<br />

- x: chave procurada<br />

Procedimento BuscaEnc( x, ant, pont );<br />

início<br />

Ant ← ptlista;<br />

Ptr ←ptlista → prox; {ptr: ponteiro <strong>de</strong> percurso}<br />

Pont ← null;<br />

enquanto ptr ≠ null faça<br />

se ptr → chave < x então<br />

Ant ← ptr; {atualiza ant e ptr}<br />

Ptr ← ptr → prox;<br />

senão se ptr → chave = x então<br />

Pont ← ptr; {chave encontrada}<br />

fim se<br />

Ptr ← null;<br />

fim se<br />

fim enquanto<br />

fim;<br />

- o parâmetro pont retorna apontan<strong>do</strong> para o elemento procura<strong>do</strong> e, ant para o<br />

elemento anterior ao procura<strong>do</strong>;<br />

- se o elemento não for encontra<strong>do</strong>, pont aponta para null e ant indica o elemento<br />

anterior ao último procura<strong>do</strong>.<br />

Inserção e remoção<br />

Após a realização da busca, as operações <strong>de</strong> inserção e remoção em uma lista<br />

enca<strong>de</strong>ada são triviais. Três fases <strong>de</strong>vem ser cumpridas:<br />

- alocação / <strong>de</strong>salocação <strong>de</strong> memória;<br />

- utilização <strong>do</strong> nó;<br />

- acerto da lista<br />

Exemplo: inserção<br />

ant<br />

ptlista<br />

nó 1 nó 2 nó 3<br />

pt


<strong>Universida<strong>de</strong></strong> <strong>Estadual</strong> <strong>de</strong> <strong>Mato</strong> <strong>Grosso</strong> <strong>do</strong> <strong>Sul</strong> - Curso <strong>de</strong> Ciência da Computação<br />

Disciplina: Estruturas <strong>de</strong> Da<strong>do</strong>s<br />

Profª. Raquel Marcia Müller<br />

15<br />

Algoritmo que realiza a inserção <strong>de</strong> um novo nó na lista:<br />

Algoritmo<br />

BuscaEnc( x, ant, pont );<br />

se pont = null então<br />

Alocar( pt ); {alocar nó}<br />

pt → info ← novo_valor;<br />

pt → chave ← x; {utilizar nó}<br />

pt → prox ← ant → prox;<br />

ant → prox ← pt; {arrumar lista}<br />

senão<br />

“Elemento já está na lista!”;<br />

fim se<br />

Fim Algoritmo;<br />

- inserção <strong>do</strong> nó conti<strong>do</strong> na variável novo, após o nó aponta<strong>do</strong> por ant;<br />

- mantém a lista or<strong>de</strong>nada.<br />

⇒ Desenhar esquema.<br />

Algoritmo que realiza a remoção <strong>de</strong> um nó da lista:<br />

Algoritmo<br />

BuscaEnc( x, ant, pont );<br />

se pont ≠ null então<br />

ant → prox ← pont → prox; {arrumar lista}<br />

valor_recupera<strong>do</strong> ← pont → info; {utilizar nó}<br />

Desocupar( pont );<br />

{<strong>de</strong>salocar memória}<br />

senão<br />

“Elemento não se encontra na lista!”;<br />

fim se<br />

Fim Algoritmo;<br />

Exercícios<br />

1. Usan<strong>do</strong> os procedimentos anteriores (inserção, remoção e busca), escreva um<br />

algoritmo que leia um conjunto <strong>de</strong> N valores numéricos, manten<strong>do</strong>-os em uma lista<br />

or<strong>de</strong>nada. Depois verifique se aparece o valor 12 nesta lista, liberan<strong>do</strong> o nó com esse<br />

valor da memória e indican<strong>do</strong> qual era a sua posição na lista.<br />

2. Apresente os procedimentos <strong>de</strong> inserção, remoção e busca, para uma lista não<br />

or<strong>de</strong>nada.<br />

3. Usan<strong>do</strong> os procedimentos escritos no exercício 2, escreva um algoritmo que leia<br />

uma string e uma palavra, armazenan<strong>do</strong>-as em duas listas, e verifique se a palavre<br />

ocorre na string.<br />

Obs.: o algoritmo <strong>de</strong> inserção <strong>de</strong>ve aceitar elementos repeti<strong>do</strong>s (ou usar o recurso da<br />

chave).<br />

Listas Circulares<br />

A busca em uma lista or<strong>de</strong>nada, vista anteriormente, po<strong>de</strong> ser consi<strong>de</strong>rada<br />

pouco eficiente quan<strong>do</strong> comparada às outras buscas anteriormente mencionadas. Uma<br />

pequena modificação na estrutura física da lista po<strong>de</strong> ser <strong>de</strong> gran<strong>de</strong> auxílio: obrigar o<br />

último nó da lista a apontar para o nó-cabeça, crian<strong>do</strong> uma lista circular enca<strong>de</strong>ada.


<strong>Universida<strong>de</strong></strong> <strong>Estadual</strong> <strong>de</strong> <strong>Mato</strong> <strong>Grosso</strong> <strong>do</strong> <strong>Sul</strong> - Curso <strong>de</strong> Ciência da Computação<br />

Disciplina: Estruturas <strong>de</strong> Da<strong>do</strong>s<br />

Profª. Raquel Marcia Müller<br />

16<br />

ptlista<br />

...<br />

nó 1 nó 2 nó n<br />

Desta forma, o teste <strong>de</strong> fim <strong>de</strong> lista nunca é satisfeito. A preocupação passa a<br />

ser um critério <strong>de</strong> parada que possa ser incorpora<strong>do</strong> ao teste da busca propriamente dita.<br />

A solução é colocar a chave procurada no nó-cabeça, <strong>de</strong> forma que uma resposta<br />

positiva seja sempre encontrada.<br />

O algoritmo abaixo apresenta a nova busca, no caso <strong>de</strong> listas or<strong>de</strong>nadas. O<br />

ponteiro pont tem o valor <strong>de</strong> ptlista se o elemento não é encontra<strong>do</strong>. Naturalmente,<br />

modificações correspon<strong>de</strong>ntes <strong>de</strong>vem ser introduzidas nos algoritmos <strong>de</strong> inserção e<br />

remoção.<br />

Algoritmo:<br />

Procedimento Busca_Circ (X, Ant, Pont); {lista circular or<strong>de</strong>nada}<br />

Início<br />

Ant ← Ptlista;<br />

Ptlista → Chave ← X;<br />

Pont ← Ptlista → Prox;<br />

enquanto Pont → Chave < X faça<br />

Ant ← Pont;<br />

Pont ← Pont → Prox;<br />

fim enquanto<br />

se Pont ≠ Ptlista então<br />

escreva "Chave localizada";<br />

senão<br />

escreva "Chave não localizada";<br />

fim se<br />

Fim;<br />

Como ficam os algoritmos <strong>de</strong> Inserção e Remoção?<br />

Os algoritmos <strong>de</strong> inserção e remoção não mudam. O que muda é que na<br />

alocação <strong>do</strong> nó-cabeça, o ponteiro prox <strong>de</strong>ve apontar não mais para null, mas para o<br />

próprio nó-cabeça.<br />

ptlista<br />

{alocação <strong>do</strong> nó-cabeça}<br />

Alocar (Ptlista);<br />

Ptlista → Prox ← Ptlista;<br />

⇒ Como ficam os algoritmos para lista circular não or<strong>de</strong>nada?


<strong>Universida<strong>de</strong></strong> <strong>Estadual</strong> <strong>de</strong> <strong>Mato</strong> <strong>Grosso</strong> <strong>do</strong> <strong>Sul</strong> - Curso <strong>de</strong> Ciência da Computação<br />

Disciplina: Estruturas <strong>de</strong> Da<strong>do</strong>s<br />

Profª. Raquel Marcia Müller<br />

17<br />

Listas Duplamente Enca<strong>de</strong>adas<br />

Nos algoritmos vistos até agora para listas lineares utilizan<strong>do</strong> alocação<br />

enca<strong>de</strong>ada, o ponteiro ant se mostrou sempre útil. Sua função é "rastrear" o ponteiro que<br />

percorre a lista, permitin<strong>do</strong> sempre o retorno ao nó anterior. Algumas vezes, entretanto,<br />

isto não é suficiente, pois po<strong>de</strong>-se <strong>de</strong>sejar o percurso da lista nos <strong>do</strong>is senti<strong>do</strong>s<br />

indiferentemente.<br />

ptlista<br />

nó1 nó2 nón<br />

A lista duplamente enca<strong>de</strong>ada incorpora um novo campo <strong>de</strong> ponteiro. Os<br />

campos <strong>de</strong> ponteiros tomam os nomes <strong>de</strong> ant e post (nó anterior e nó seguinte,<br />

respectivamente).<br />

Os algoritmos <strong>de</strong> busca, inserção e remoção em tabelas or<strong>de</strong>nadas são muito<br />

simples. Na busca, a função retorna indican<strong>do</strong> o nó procura<strong>do</strong> ou, se este não foi<br />

encontra<strong>do</strong>, o nó que seria seu consecutivo.<br />

Busca em uma lista duplamente enca<strong>de</strong>ada or<strong>de</strong>nada:<br />

Função Busca_Dup (X) : ponteiro;<br />

Início<br />

Ultimo ← Ptlista → Ant;<br />

se X ≤ Ultimo → Chave então<br />

Pont ← Ptlista → Post;<br />

enquanto Pont → Chave < X faça<br />

Pont ← Pont → Prox;<br />

fim enquanto<br />

Busca_Dup ← Pont;<br />

senão<br />

Busca_Dup ← Ptlista;<br />

fim se<br />

Fim;<br />

Inserção em lista duplamente enca<strong>de</strong>ada or<strong>de</strong>nada:<br />

ptlista<br />

nó1 nó2 nón<br />

pt


<strong>Universida<strong>de</strong></strong> <strong>Estadual</strong> <strong>de</strong> <strong>Mato</strong> <strong>Grosso</strong> <strong>do</strong> <strong>Sul</strong> - Curso <strong>de</strong> Ciência da Computação<br />

Disciplina: Estruturas <strong>de</strong> Da<strong>do</strong>s<br />

Profª. Raquel Marcia Müller<br />

18<br />

Algoritmo<br />

Pont ← Busca_Dup (X);<br />

se Pont = Ptlista ou Pont → Chave ≠ X então<br />

Anterior ← Pont → Ant;<br />

Ocupar (Pt);<br />

Pt → Info ← Novo_valor;<br />

Pt → Chave ← X;<br />

Pt → Ant ← Anterior;<br />

Pt → Post ← Pont;<br />

Anterior → Post ← Pt;<br />

Pont → Ant ← Pt;<br />

senão<br />

escreva "Elemento já se encontra na lista";<br />

fim se<br />

Fim Algoritmo<br />

Remoção em lista duplamente enca<strong>de</strong>ada or<strong>de</strong>nada:<br />

Algoritmo<br />

Pont ← Busca_Dup (X);<br />

se Pont ≠ Ptlista e Pont → Chave = X então<br />

Anterior ← Pont → Ant;<br />

Posterior ← Pont → Post;<br />

Anterior → Post ← Posterior;<br />

Posterior → Ant ← Anterior;<br />

Valor_recupera<strong>do</strong> ← Pont → Info;<br />

Desocupar (Pont);<br />

senão<br />

escreva "Elemento não se encontra na lista";<br />

fim se<br />

Fim Algoritmo<br />

ptlista<br />

nó1 nó2 nón<br />

pont<br />

Aplicação: Or<strong>de</strong>nação Topológica<br />

Uso pontencial todas as vezes em que o problema aborda<strong>do</strong> envolve uma<br />

or<strong>de</strong>m parcial.<br />

Uma or<strong>de</strong>m parcial <strong>de</strong> um conjunto S é uma relação entre os objetos <strong>de</strong> S,<br />

representada pelo símbolo ≤, satisfazen<strong>do</strong> as seguintes proprieda<strong>de</strong>s para quaisquer<br />

objetos x, y e z, não necessariamente distintos em S:<br />

i) se x ≤ y e y ≤ z, então x ≤ z (transitiva);


<strong>Universida<strong>de</strong></strong> <strong>Estadual</strong> <strong>de</strong> <strong>Mato</strong> <strong>Grosso</strong> <strong>do</strong> <strong>Sul</strong> - Curso <strong>de</strong> Ciência da Computação<br />

Disciplina: Estruturas <strong>de</strong> Da<strong>do</strong>s<br />

Profª. Raquel Marcia Müller<br />

19<br />

ii) se x ≤ y e y ≤ x, então x = y (anti-simétrica);<br />

iii) x ≤ x (reflexiva);<br />

A notação x ≤ y po<strong>de</strong> ser lida "x prece<strong>de</strong> ou iguala y".<br />

Se x ≤ y e x = y, escreve-se x < y e diz-se "x prece<strong>de</strong> y". Tem-se então:<br />

i') se x < y e y < z, então x < z (transitiva);<br />

ii') se x < y, então y ∠ x (assimétrica);<br />

iii') x ∠ x (irreflexiva).<br />

A notação y ∠ x significa "y não prece<strong>de</strong> x". Assume-se aqui que S é um<br />

conjunto finito, uma vez que se <strong>de</strong>seja trabalhar no computa<strong>do</strong>r.<br />

Exemplo <strong>de</strong> aplicação:<br />

Execução <strong>de</strong> um conjunto <strong>de</strong> tarefas necessárias, por exemplo, à montagem <strong>de</strong><br />

um automóvel. Uma or<strong>de</strong>m parcial <strong>de</strong>ssas tarefas po<strong>de</strong> ser representada assim:<br />

1 5<br />

3 2 8<br />

4 6<br />

7<br />

Cada caixa na figura representa uma tarefa a ser executada; cada tarefa é<br />

numerada arbitrariamente. Se existe a indicação <strong>de</strong> um caminho da caixa x para a caixa<br />

y, isto significa que a tarefa x <strong>de</strong>ve ser executada antes da tarefa y.<br />

A or<strong>de</strong>nação topológica trata <strong>de</strong> imergir a or<strong>de</strong>m parcial em uma or<strong>de</strong>m linear,<br />

isto é, rearrumar os objetos numa seqüência a 1 , a 2 , ..., a n , tal que sempre que a j < a k , temse<br />

j < k.<br />

1 5 2 8 6 7 3<br />

4


<strong>Universida<strong>de</strong></strong> <strong>Estadual</strong> <strong>de</strong> <strong>Mato</strong> <strong>Grosso</strong> <strong>do</strong> <strong>Sul</strong> - Curso <strong>de</strong> Ciência da Computação<br />

Disciplina: Estruturas <strong>de</strong> Da<strong>do</strong>s<br />

Profª. Raquel Marcia Müller<br />

20<br />

Como obter a or<strong>de</strong>nação topológica:<br />

- inicialmente, consi<strong>de</strong>ra-se um objeto que não é precedi<strong>do</strong> por nenhum outro na<br />

or<strong>de</strong>m parcial. Esse objeto é o primeiro na saída, isto é, na or<strong>de</strong>m final;<br />

- removemos o objeto <strong>do</strong> conjunto S;<br />

- o conjunto resultante obe<strong>de</strong>ce novamente a uma or<strong>de</strong>m parcial. O processo é, então,<br />

repeti<strong>do</strong> até que to<strong>do</strong> o conjunto esteja or<strong>de</strong>na<strong>do</strong>.<br />

Implementação:<br />

Os objetos a serem or<strong>de</strong>na<strong>do</strong>s são numera<strong>do</strong>s <strong>de</strong> 1 a n, em qualquer or<strong>de</strong>m, e<br />

aloca<strong>do</strong>s seqüencialmente na memória. A entrada <strong>do</strong> algoritmo são os pares (j, k),<br />

significan<strong>do</strong> que o objeto j prece<strong>de</strong> o objeto k. O número <strong>de</strong> objetos n e o número <strong>de</strong><br />

pares m também são forneci<strong>do</strong>s. Devem constar da entrada somente os pares<br />

necessários à caracterização da or<strong>de</strong>m parcial; pares supérfluos não constituem erro.<br />

Ex.: o par (8,7) é <strong>de</strong>snecessário, pois po<strong>de</strong> ser <strong>de</strong>duzi<strong>do</strong> <strong>do</strong>s pares (8,6) e (6,7).<br />

0 0 -<br />

1 0 3 2 -<br />

2 2 6 -<br />

3 2 4 -<br />

4 1 -<br />

5 0 2 8 -<br />

6 2 7 -<br />

7 1 3 -<br />

8 1 6 -<br />

CB<br />

O algoritmo lida com n listas enca<strong>de</strong>adas, uma para cada objeto. Na lista i,<br />

estão indica<strong>do</strong>s to<strong>do</strong>s os objetos k que aparecem em pares (i, k), isto é, sucessores <strong>de</strong> i.<br />

Para cada lista é cria<strong>do</strong> um nó-cabeça, chama<strong>do</strong> CB. No nó-cabeça da lista i, além <strong>do</strong><br />

ponteiro para os sucessores <strong>de</strong> i, está armazena<strong>do</strong> o número <strong>de</strong> pares (k, i) existentes,<br />

isto é, o número <strong>de</strong> vezes em que i aparece como sucessor <strong>de</strong> outro objeto. Essa<br />

informação é <strong>de</strong>nominada conta<strong>do</strong>r.<br />

Uma vez organizadas as listas, os nós-cabeça são percorri<strong>do</strong>s em busca <strong>de</strong> um<br />

objeto que não seja sucessor <strong>de</strong> nenhum outro, isto é, cujo campo conta<strong>do</strong>r seja nulo<br />

(zero). To<strong>do</strong>s aqueles que obe<strong>de</strong>cem tal condição, são enca<strong>de</strong>a<strong>do</strong>s pelo próprio campo<br />

conta<strong>do</strong>r, que passa a ter nova função. Em seguida, o objeto é retira<strong>do</strong> da tabela<br />

original, isto é, to<strong>do</strong>s os conta<strong>do</strong>res <strong>de</strong> seus sucessores são <strong>de</strong>crementa<strong>do</strong>s e<br />

imediatamente testa<strong>do</strong>s para que, ao chegarem a zero, sejam incluí<strong>do</strong>s na seqüência <strong>de</strong><br />

saída. O algoritmo termina quan<strong>do</strong> to<strong>do</strong>s os objetos forem retira<strong>do</strong>s.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!