391 66 125MB
Portuguese Pages 450 Year 2010
dados
algoritmos, análise da complexidade e implementações em JAVA e C/C++
Ana Fernanda Gomes Ascencio & Braziela Santos de Araújo
---PEARSON
•
Companion
VVebsita
estruturas d dados algoritmos, análise da complexidade e implementações em JAVA e C/C++
Ana Fernanda Gomes Ascencio & Graziela Santos de Araújo
estruturas dados algoritmos, análise da complexidade e implementações em JAVA e C/C++
------PEARSON São Pa ulo
Brasil Argentina Colômbia Costa Rica Chile Espanha Guatemala México Peru Porto Rico Venezuela
" ... plante seu próprio jardim e embeleze a sua própria alma, em vez de esperar que alguém lhe traga flores ... "
William Shakespeare
"Aos meus filhos, Eduardo e Pedro, amores eternos e verdadeiros."
Ana Fernanda Gomes Ascencio
"Ao meu pai (in memorian), que em todos os dias de sua vida semeou amor, sabedoria, compreensão, paciência, admiração e apoio incondicional."
Graziela Santos de Araújo
© 2010 by Pearson Education do Brasil
Todos os direitos reservados. Nenhuma parte desta publicação poderá ser reproduzida ou transmitida de qualquer modo ou por qualquer outro meio, eletrônico ou mecânico, incluindo fotocópia, gravação ou qualquer outro tipo de sistema de armazenamento e tra nsmissão de informação, sem prévia autorização, por escrito, da Pearson Education do Brasil.
Diretor editorial: Roger Trimer Gerente editorial: Sabrina Cairo Supervisor de produção editorial: Marcelo Françozo Editor de desenvolvimento: Yuri Bilesl O. Portanto, qualquer função polinomial positiva cresce mais rapidamente que qualquer função polilogarítmica.
Somatórios Os somatórios aparecem em todas as partes da matemática. Na análise de algoritmos, quando o tempo de execução de um algoritmo é calculado, é comum aparecer um somatório de termos durante a determinação do número de vezes que o conjunto de instruções mais importante do algoritmo é executado. Portanto, a seguir são apresentados alguns dos principais somatórios que aparecem e podem ser utilizados para encontrar o tempo de execução dos algoritmos. O termo "soma" também será utilizado para indicar um somatório. Dada a sequência de números a1, a2 , ••• ,a., a soma finita a1 + a2 + ... + a. pode ser escrita como:
Se n = O, o valor do somatório é definido ser O. Se n não é um inteiro, assume-se que o limite superior da soma é j. Da mesma forma, se a soma começa com k = x, onde x não é um inteiro, considera -se que o valor inicial, ou limite inferior, para a soma é x j. O valor de uma soma finita é sempre bem definido e seus termos podem ser adicionados em qualquer ordem.
ln
l
A seguinte soma de termos 1 + 2
n
+ 4 + ... + 2" pode ser escrita como E 2", onde o i=O
valor inferior indica que o primeiro valor começa com o expoente i = O, ou seja, 2º = 1 e o último termo da soma é o termo com expoente n, ou seja, 2". 1
Outro exemplo de soma é 1 + -
+ ... + -1 , que pode ser reescrito como E" -1 .
n k=I k Um item-chave na manipulação de somas está na h abilidade de transformar somas em outras mais simples ou deixá-las mais próximas de uma expressão objetivo. Para 2
Capítulo 1 o
Análise de algoritmo
19
isso, podem ser utilizadas três regras. Considere I qualquer conjunto finito de inteiros. Os somatórios indexados por I podem ser transformados por meio das três regras indicadas no Quadro 1.8. Quadro 1.8
Transformação de somatórios indexados por orações com somatórios
I: ca;
= cI:a;
iEI
(distributividade)
iEI
(associatividade) iEI
I:a; = iE I
iEI
I: ap(i) p(i)EI
iEI
(comutatividade)
A regra de distributividade permite mover constantes para dentro e para fora de um I. A regra da associatividade permite quebrar um I em duas partes ou combinar dois somatórios em um. A comutatividade p ermite colocar os termos da soma em qualquer ordem, ou seja, o somatório 1 + 2 + ... + n é igual ao somatório n + ... + 2 + 1. Dada uma sequência de números a1, a2, ... , a soma infinita a 1 + a2 + ... pode serescrita como:
que é interpretada como
Se o limite não existe, a soma diverge; caso contrário, ela converge. Os termos de uma soma convergente nem sempre podem ser adicionados em qualquer ordem. A seguir são mostrados alguns somatórios que aparecem com frequ ência na análise de algoritmos.
a) Série aritmética Segundo Oliveira (2008), uma sequência de números a1 + a2 + a3 ... + antal que a; - a;_1 = q para 1 < k s n e q constante é chamada de progressão aritmética (PA) . Por exemplo, a sequência (5,7, 9, 11,13, 15,17) é uma progressão aritmética, pois os seu s elementos são formados pela soma de seu antecessor com o valor constante q = 2. A sen quência 1 + 2 + 3 + ... + n = L k é outra progressão aritmética com valor constante q = 1. k~I
Dada uma PA finita qualquer, a soma de seus termos é chamada série aritmética e o seu cálculo é dado pela fórmula:
onde a1 é o primeiro termo da sequência, an é o ú ltimo termo da sequência e n é o número de elementos da soma.
20
Estruturas de dados
Exemplo: O valor da soma 1 + 2
(1 + n) · n + 3 +...+ n é --- = 2
b) Série geométrica Segundo Oliveira (2008), uma sequência de números a1 + a2 + a 3 ••• + antal que a/ a;_ 1 = q para 1 < k ~ n e q constante é chamada de progressão geométrica (PG). Por exemplo, a sequência (1,2,4,8,16,32,64) é uma PG com valor constante q = 2. A sequência (5,15,45,135,405) é uma PG com valor constante q = 3. A sequência (2,1,1/2,1/4,1/8,1/16) é uma PG com valor constante q = 1/2. Dada uma PG finita qualquer, a soma de seus termos é chamada série geométrica e seu cálculo é dado pela fórmula:
onde a 1 é o primeiro termo da sequência, q é a razão da progressão e n é o número de termos da PG. Exemplo: O valor da soma 1 1. (2 7
+ 2 + 4 + 8 + 16 + 32 + 64 é 1)
-
1 · (128 - 1) = 127 = 127 1 1
2-1
c) Soma geométrica infinita Quando o somatório de termos é infinito e lxl < 1, a série infinita, decrescente e geométrica é calculada como: 00
Z::::xk
1
=--
(Equação 1.6)
1-x
k=o
d) Série harmônica Para inteiros positivos n, o n-ésimo número harmônico é H n
= l + -21 + -31 + -41 + ... + -n1 n
1
= I::k k=I
= ln n + 0(1) e) Somas integrais e diferenciais Fórmulas adicionais podem ser obtidas integrando ou derivando as fórmulas apresentadas. Por exemplo, derivando ambos os lados da soma infinita e geométrica da Equação 1.6 e multiplicando por x, obtém-se 00
Z::::k . xk k=O
=
X (1-
X)2
2 o
Algoritmos de ordenação ebusca
Há situações em que é necessário ordenar dados. Para esse procedimento existem algoritmos de ordenação. As seções a seguir abordam os seguintes algoritmos: BUBBLE SORT, INSERTION SORT, SELECTION SORT, MERGE SORT, QUICK SORT e HEAP SORT.
Em outras situações, ocorre a necessidade de encontrar um dado em um conjunto ordenado ou desordenado. Para esse fim, existem os algoritmos de busca descritos nas duas últimas seções deste capítulo .
.___Algoritmo de ordenação por troe~ (BUBBLE SORTI Neste algoritmo de ordenação serão efetuadas comparações entre os dados armazenados em um vetor de tamanho n. Cada elemento de posição i será comparado com o elemento de posição i+l , e quando a ordenação procurada (crescente ou decrescente) é encontrada, uma troca de posições entre os elementos é feita. Assim, um laço com a quantidade de elementos do vetor será executado (for ( j = l; j 4 Q V Qtroca
o
Q
o
1
15 1 4 1 Q
~
1
14 1 4 1
V
[I]
Q
o 1 14 1 5 1
o 4
1 2 3 4 5 2 1 8 Q 5>2 QV Qtroca
aux
1 2 2 5 1 1 1 Q
~
1 2 l 2 12 1 Q
1 2 l2 15 1
V
[I]
[I]
aux
o 4
1 2
aux
2 3 4 2 3 5 1 8 5 1 Q 1 1 1 Q 5 > 1 Q VQtroca ~
l
[Il
2
3 1 111 Q
2
3 l1 15 1
V
[Il
aux
o 4
1 2
2 1
-
[I]
aux
aux
3 4 5 8 5 > 8 Q F Q não troca
2" execução do laço O 1 2 3 4 4 2 1 5 8 4 > 2 Q V Q troca
Q
o 1
4
~
1
1 2
1
Q
o
1 2 l 2 1 1
o
V
[TI
[TI
aux
o 1 2 12
3 4 4 11 5 I B I 4 > 1 Q VQ troca
1
1 2 4 l 1 1 Q
~
aux l
1 2 1 l 1 1 Q
1 2 l1 14 1
V
[TI
aux
o 1 2 12 11
3
-
1 4 l2 1 1
Q
aux
4 B I
415 4 > 5 Q Fç,não troca
o 1 2 1 2 1 1 14
3 4 5 18 5 > 8 Q F Q não troca
3" execução do laço
01234 01 21458 Q l 2 111 2 > 1 Q V Q troca ~
0aux
O l
1
-
1
1 2
0aux
1
Capítulo 2
o
1 2
2 4
2 >4
o
1 2
2 4
3 5
2
2 4
4 8
Q F Q não troca
3 5
4 >5
o
Algoritmos de ordenação e busca
o
3 5
4 8
Q FQ
não troca
4 8
Q FQ
5 > 8
não troca
4• execução do laço O
2
3
4
2
4
5
8
1 >2
Q
o
2 4
2
2 >4
o
F Q não troca
4
5
8
Q F Q não troca
2 4
1 2
3
4
3
8
5
4 >5
o 1
1
1
1 2
1
2 4
Q F Q não troca
4 3 5 1 8 5 >8
Q FQ
não troca
5' execução do laço Apesar de o vetor já estar ordenado, mais uma execução do laço será realizada.
o
1 2
2 4
1>2
Q
O
2 4
1
1
2
2 >4
1
3 5
1
4 8
1
F Q não troca
3 5
4 8
Q F Q não troca
23
24
Estruturas de dados
o 2
2
3
4
5
4 >5
o 2
2
3
4
5
4 8
Q F Q não troca 4 8
5 > 8
Q FQ
não troca
algoritmo declare X[5], n , i , aux numérico // carregando os números no vetor parai+- O até 4 faça início escreva " Digite o ", i+l , " 0 número : leia X[i] fim // ordenando de forma crescente // laço com a quantidade de elementos do vetor para n +- 1 até 5 faça início // l a ço que percorre da primeira à // penúltima posição do vetor para i +- O até 3 faça início se (X[i] > X[i+ ll) então início aux +- X[i] X[i] +- X[i+l] X[i+l] +- a ux fim fim fim // mostrando o vetor ordenado parai+- O até 4 faça início escreva i+l," 0 número : " , X[i] fim fim_alg o ritmo .
Capítulo 2
lõo11011 1010010 0011100 J
A V A
o
Algoritmos de ordena ção e busca
25
i mpo rt j ava . u til.*; public c l ass bubbl e sort {
public static void main (String args[]) {
int X[] = new int[5]; int n , i , aux ; Scanner entrada= new Scanner (Sys t em .in) ; // carregando os números no vetor for (i=O ; i < =4 ; i++) {
Syst em . o u t . pr i n tl n ( " Di g ite o "+ (i+l ) +"º número : " ) ; X[i] = entra d a . nex ti nt() ; }
// ordenando de forma crescent e // laço com a quantidade de elementos do vetor for (n=l ; n < =5 ; n++) {
// laço que percorre da primeira à // penúltima posição do vetor for (i=O ; i < =3; i ++ ) {
if (X[i] > X[i+l])
aux X [i] ; X[i] = X[i+l] ; X[i + l] = a ux ;
}
// mo s tra ndo o ve t or ordena do fo r (i = O; i < = 4 ; i + +) {
Syst em . out .pr i n tl n ( (i + l) + " º núme ro : " + X [i ]); } }
# i n c lude < i o s t r e am.h> #include v o id ma in () int X[ 5 ] , n, i, a ux; clrsc r(); // c arregando os n ú me r os n o v eto r
26 Estruturas de dados for (i=O; i>novo->num; if (inicio== NULL) {
li a lista estava vazia li e o e l emen t o inserido será li o primeiro e o último inicio= novo ; fim= novo; fim- >prox = NULL ; else
li a li s t a j á conté m e l emen t os e li o novo elemento li será inserido no fim da lis ta fim- >prox = novo ; fim= no v o ; fim- >prox=NULL ; cout # i nc l ude void main () //De fin i ndo o r e g i stro que // r epr esentará cada e l emento da li sta st ruct LI STA int num; LIS TA *pr o x; };
li li li li
a l ista es tá v az i a , l o go , o p o n t eiro inic i o têm o val o r NULL o p o nt e iro inic i o con t erá o e nde r eço d o primeiro e l e me n to d a lista LISTA *inic i o = NULL; li o ponteir o fim c o nt e rá o ende r eço li do ú l t imo e l e me n to da li sta LISTA *fim = NULL; li o po n te iro aux é um p o n te iro auxilia r LIS TA *aux ; li o pon teir o a n ter i o r é um pon t eiro auxiliar LIS TA *a n terior; // a presenta ndo o men u d e o p ções int op , n ume r o , achou ; do
Capítulo 3
o
Estrutura de dados do t ipo listas
clrscr() ; coutant ;
i f (op
5)
139
140
Estruturas de dados
if (inicio== NULL)
li a lista está vazia coutpro x; if (inicio != NULL) inicio->ant = NULL ;
delete (aux); aux = inicio; e l se if (aux == ílm)
Capítulo 3
o
Estrutura de dados do t ipo listas
141
li li li II
o núme ro a ser removido é o último da lista fim= fim- >ant ; fim- >prox = NULL ; delete (aux); aux = NULL; else
{
li o número a ser li removido li está no meio li da lista aux->ant- >prox ._ aux->prox; aux->prox->ant ._ aux->ant; LISTA *aux 2 ; aux2 = aux->prox; delete (aux); aux = aux2;
else aux
aux- >prox;
(achou == O) coutprox;
if
(op
3)
if (inicio== NULL)
li a lista está vazia coutprox = inicio; inicio= novo; fim- >prox = inici o ; coutprox = inici o ; else
li a lista já contém elementos li e o novo elemento li será inse rido no fim d a li s t a fim- >pro x = n o vo ; fim = no vo; fim- >pro x = inici o ; coutnum == numero) {
li o número digitado li foi encontrado na lista li e será remo vido achou= acho u+ 1; if (aux == inicio)
li o número a ser removido li é o primeiro da lista inicio= aux->prox; inicio- >ant = fim ; fim- >prox = inicio; delete (aux); aux = inicio ; else if (aux == fim) {
li o número a ser li removido li é o último da lista fim = fim- >ant ; fim- >prox = ini c i o ; i n ici o - >an t = fim; delete(aux); aux = NULL; else
li o número a se r li removido li es t á n o me i o da li s t a aux->ant->prox = a ux'-+ >p r ox ; aux- >prox- >ant = aux- >ant ; LISTA *aux2; aux2 = aux ; aux = aux->prox; delete(aux2);
Capítulo 3
o
Estrutura de dados do t ipo listas
else aux
elemento
aux->prox;
elemento+ 1;
while (elemento 4 Q V Q troca
4
01234567 heap ._I___._11_8_._I_4--'--I_7_._l_10_._l_15_,_l_____,I'------' o procedimento heap_fica será executado para o elemento da posição 2 01234567 heap ._I___._11_8_._I_4--'--I_7_._l_10_._l_15_,_l_____,I'------' maior filho Q 15 15 > 4QVQtroca
4
01234567 heap ._I~11_ 8 l._1_5l._7_1._1_0l._4~1~1~
4
A ilustração de um heap mínimo funciona da mesma forma, alterando apenas a condição para que só haja troca quando o pai possui prioridade maior que a do filho. Logo, a condição para troca será: i nd > 1 E pai ( i nd ) > num. lõo11011 1010010 0011100
J A V A
impo r t java . util . *; public class Heap_ Maximo {
// declarando o vetor com capacidade de n o máximo 10 // números static int vet[]= new int[ll]; public static void main( String[ ] args ) {
Scanner entrada= new Scanner(System . in); int op, tam=O , ind, num;
210
Estruturas de dados
do System.out .println ("\nMENU DE OPÇÕES - HEAP MÁXIM::>\n"); System. out . println ("1 - Inserir elemento na l i sta de prioridades") ; System. out . println ("2 - Consultar o elemento de maior prioridade") ; System . out. println ("3 - Remover o elemento de mai or prioridade") ; System. out. println ("4 - Consultar toda a lista"); System. out. println ("5 - Sair"); System. out. print ("Digite sua opção : ") ; op = entrada.nextint();
i f ( op < 1 1 1 op > 5) System. out .println ("Opção inválida! ! "); else if (op==l) {
// verifica se ainda existe espaço disponível no vetor // para inserção do novo número if(tam < vet.length-1) {
tam++; System . out . print ("Digi te um número : ") ; // leitura do número a ser inserido num= entrada.nextint(); ind=tarn; while( ind> l && vet[Pai(ind)] < num) vet[ind] = vet[Pai(ind)]; ind=Pai (ind); vet [ ind] =num; System . out . println ("Número inserido"); else System . out . println("Lista de prioridades ..,. Lotada!");
else if (op==2) if (tam= =0) System. out . prin t ln ("Lista de prioridades ._. vazia!");
Capítulo 5
o
Estrutura de dados do tipo lista de prioridades
211
else System . out. println ("Elemento de maior ._. prioridade: " +vet [ 1]) ;
else if (op==3) if (tam==O) System.out .println ("Lista de prioridades vazia!"); else
int maior__prior=vet[l]; vet [ 1] =vet [tam]; tam--; heap_fica ( 1 , taro); System . out. println ("O elemento removido : " +maior_prior) ;
else if (op==4) if (tam==O) System.out.println("Lista de prioridades vazia!"); else System . out . println ("\nTodos os elementos ._. da lis ta de prioridades\n"); fo r (int j = l; j vet[i]) maior = 2*i+l; else if(vet[f_dir] > vet[f_esq] && vet[f_dir] > vet[i]) maior = 2*i; else if (2*i vet[i]) maior = 2*i; if (maior ! = i) aux = vet[i]; vet[i] = vet[maior]; vet[maior] = aux; heap_fica(maior , qtde);
#include #include int Pai (int x) return xl2;
void heap_fica(int vet[], int i, int qtde) int f_esq , f_dir, mai o r , aux ; maior = i;
Capítulo 5
o
Estrutura de dados do tipo lista de prioridades
213
if (2*i+l = vet[f_dir] && vet[f_esq] > vet[i]) maior = 2*i+l ; else if (ve t[f_dir] > vet[f esq] && vet[f_dir] > vet[i]) maior= 2*i ; else if (2*i vet[i]) maior = 2*i ; if (maior ! = i) aux = vet[i]; vet[i] = vet[maior] ; vet[maior] = aux; heap_fica(vet , maior,qtde);
void main ()
li declarando o vetor com capacidade de n o má ximo 10 li números int vet [11]; int op, tam=O , do
ind, num;
{
clrscr( ); cout num; ind=tam; while( ind>l && vet[Pai(ind)]< num) vet [ind] =vet [Pai (ind)] ; ind=Pai (ind); vet[ind]=num; cout < < "Número inserido"; else cout = 1 O > = 1 + F + novo n' permanece na posição onde está
i
1
num
[TI [!TI
Capítulo 5
Estrutura de dados do tipo lista de prioridades
o
5• operação Inserção do n~33 na lista de prioridades (heap min-max)
O 1
2
3
4
5
6
7
8
9
10 1
num
i
1
0
§]
4 nivel = log,i + 1 = 3 . . nível ímpar + nível mínimo pai= i/2 = 4/2 =2 verifica se a IX)sição do novo nia- possui pai pai > "" 1 2 >"" 1 .V.verifica se o novo ~émaiorqueseu pai heap(Q > heap(paQ . .33 > 2s+v . . trocae atualizai para a posição do pai, i = 2
+
012345678
10
9 1
i
1
num
[I] §]
4 avo = i/4 = 2/4 = O verWica se a posição i possui avô + avo > = 1 O > = 1 + F + novo n' permanece na posição onde está
6" operação Inserção do n2 28 na lista de prioridades (heap min-max) 0
1
2345678
10
9 1
i
1
ITJ
4 nivel"" log2 i + 1 ""3 . . nível ímpar+ nível mínimo pai=V2=512=2 verWica se a posição do novo n' possui pai + pai > = 1 2 > = 1 +v +verifica se o novo n' é maior que seu pai heap(i) > heap(pai) + 2s > 33 . . F +verifica se o novo n-' possui avô avo = i/4 = 5/4 = 1 verifica se a posição i possui avô + avo "" > "" 1 1 > "" 1 V . verifica se o novo n'I é menor que seu avô heap(i) >heap(pai) . . 28 < 17 . . F.novo n-' permanece na posição onde está
+
num
e]
219
220
Estruturas de dados 7"- operação Inserção do n2 14 na lista de prioridades (heap min-max)
O 1
2
3
4
5
6
7
8
9
10 1
i
1
num
[I] ~
4 nivel"" log) + 1 ""3 . . nível ímpar . . nfvel mínimo
pai=i/2=612=3 verifica se a posição do novo n" possui pai • pai > = 1 3 > = 1 • V . verifica se o novo n' é maior que seu pai heap(i) > heap(paQ .14 > 20 .F.vermca seo novo n' possui avô avo= i/4 =614 = 1 verifica se a posição i possui avô .avo > "" 1 1 > = 1 • V . verifica se o novo n' é menor que seu avô heap(i) > heap(avô. 14 < 17. V.troca e atualizai para a posição do avô, i = 1
012345678
10
9 1
i
1
num
O] ~
4 avo = i/4 = 1/4 = O verifica se a posição i possui avô . avo > = 1 O > = 1 • F . novo n' pemianece na posição onde está
S"operação Inserção do n2 46 na lista de prioridades (heap min-max)
O 1
2
3
4
5
6
7
8
10
9 1
4
i
1
num
[D~
7
nivel = log,i + 1 = 3 . nivel ímpar. nivel mínimo pai = i/2 = 712 = 3 verifica se a posição do novo n' possui pai • pai > = 1 3 > "" 1 • V . verifica se o novo N2 é maior que seu pai hoop(i) > heap(pai) .46 > 20 . V. troca e atualizai para a posição do pai, í = 3
Capítulo 5
O 1
2
3
4
o
5
Estrutura de dados do tipo lista de prioridades
6
7
8
10
9 1
num
i
1
4
[TI ~
7
avo = V4 = 3/4 = O verifica se a posição i possui avô . . avo > ~ 1 O > = 1+ F + novo n' permanece na posição onde está
9" operação Inserção do n" 12 na lista de prioridades (heap min-max)
heap
o 1 2 3 4 5 6 7 8 9 10 ~I~I1_ 4~13_31~4~ 61~25~1~28~1~1~ 7l_2o~l_12~l~l~I
num
i
0
@]
nivel = log,i + 1 = 4 + nível par+ nível máximo pai = i/2 = 8/2 =4 verifica se a posição do novo n2 possui pai pai > "" 1 4 >"" 1 +v+verifica se o novo naé menor que seu pai heap(i) < heap(paQ + 12 < 25 +v+troca e atualizai para a posição do pai, i = 4
+
heap
o 1 2 3 4 5 6 7 8 9 10 ~I~I1_4~13~3 14_6~11_2~l2_a~I1_1~12_o~l2_s~I~I~I
i
0
num
@]
avo = i/4 = 4/4 = 1 verifica se a posição i possui avô + avo > "" 1 > "" verifica se o novo na é menor que seu avô heap(i) < heap(avo) . . 12 < 14+v+troca e atualizai para a posição do avô, i = 1
1 1+V+ heap
o 1 2 3 4 5 6 7 8 9 10 ~I~I1_2~13~3 14_6~11_4~12_a~I1_?~l2_o~l2_s~I~I~I
i
num
[TI @]
221
222
Estruturas de dados
avo=i/4=1I4=0 verifica se a posição i possui avô . . avo > "" 1 O > = 1 + F + novo n' permanece na posição onde está
1O" operação Inserção do nª 57 na lista de prioridades (heap min-max) heap
I
012345678910 l 12 l 33 l 46l141281171201251571
num
i
0
@]
nivel = log) + 1 = 4 + nível par + nível máximo pai = i/2 = 9/2 = 4 verifica se a posição do novo n2 possui pai pai > "" 1 4 > ,,,,_ 1 +v+verificaseo novo ~émenorqueseu pai heap(Q > heap(pai) . 57 < 14 +F+verifica se o novo n' possui avô avo = V4 = 9/4 = 2 verifica se a posição i possui avô + avo > = 1 2 > "" 1 . . V +verifica se o novo~ é maior que seu avô heap(Q > heap(avo. 57 > 33+ v+ troca e atualizai para a posição do avô, i = 2
+
O heap
1
2
3
4
5
6
7
8
9
10
l 12 ls7 l46 l 14 l 2a l 1? l 20 l 25 l 33 I
i
0
num
@]
Capítulo 5
Estrutura de dados do tipo lista de prioridades
o
avo =i/4 =2/4 =O verifica se a posição i possui avô • avo > = 1 O> = 1. F novo n" pemanece na posição onde está
+
11§ operação Inserção do n" 8 na lista de prioridades (heap min-max)
heap
I
O
1 l
2
3
4
I
5
6
7
8
9
10
12 1 57 l 46 l 14 28 1 17 1 20 l 25 1 33 1 8
9
num
i
~
0
10
nivel =log,i + 1 =4 . nível par. nível máximo pai =i/2 =10/2 =5 verifica se a posição do novo n" possui pai • pai > = 1 5 > = 1 • V . verifica se o novo n" é menor que seu pai heap(i) < heap(pai).8 < 28.V. t roca e atualizai para a posição do pai, i = 5
O
heap
1
2
3
4
5
6
7
8
9
10
i
num
I l12157 l46 l14I 8 117 120 125 1331281 0 0
9
10
223
224
Estruturas de dados avo= i/4 = 5/4= 1 verifica se a posição i possui avô +avo > _,, , 1 1 >"" 1.V.verificaseo novo n'lémenorqueseu avô heap(i) "" 1 O > = 1 . . F • novo n' permanece onde está
1Z' operação Remoção do elemento de maior prioridade da lista de prioridades (heap min-max)
O heapl
8
1 2 3 4 5 6 7 8 9 10 8 l57l46l14112l11l20l25l33l2sl
9
Iam
~
10
estrutura heap min_max . . o elemento de maior prioridade está na posição 2 ou 3 verifica qual o maior elemento . . heap(2) > heap(3). 57 > 46 . V elemento da posição 2 será removido elemento da última posição ocupada será copiado para a posição 2 e será descartado analisar as prioridades heap para o novo valor da posição 2
O heap
1
1 2 3 4 5 6 7 8 9 10 8 1 28 1 46 114 112117 120 125 133 1
Iam
i
[I][I]
Capítulo 5
o
Estrutura de dados do tipo lista de prioridades
nivel = log,i + 1 = 2 . . nível par . . nível máximo verifica se o elemento da posição i tem descendentes • 2 • i < ""tam 2 • 2 < = 9 . . V . . o elemento da posição i tem descendentes encontrar a posição do maior elemento entre os descendentes (filhos e netos) m = posição do maior descendente do elemento da posição i m = 9 . compara o elemento da posição i com o elemento da posição m heap(m) > heaprn . . heap(9) > heap(2) . . 33 > 28 • V.troca
heap
012345678910 8 33 146 1141 12 171 201251281
l
I
tam
[I]
i
0
verifica se elemento da posição m é neto • m > "" 4 • i 9 > =4 • 2 • V • é neto, verWicar as propriedades heap com o pai pai = m/2 = 9/2 = 4 heap(pai) > he~(m) . . heap(4) > heap(9) 14 > 28 . . F • elementos permanecem onde estão
13° operação Remoção do elemento de menor prioridade da lista de prioridades (heap min-max) heap
012345678910 8 33 146 1141 121 17 1 20 125 128 1 1
l
tam
[I]
estrutura heap min_max . . o elemento de menor prioridade está na posição 1 elemento da posição 1 será removido elemento da última posição ocupada será c opiado para a posição 1 e será descartado analisar as propriedades heap para o novo valor da posição 1
225
226
Estruturas de dados
O 1
heap
2
3
4
5
6
7
8
I l2a l33 l46 l14 l12 l 11 l20 l2s l
10
9 1
tam
1
0
i
[TI
nivel = log) + 1 = 1 . . nível ímpar+ nível mínimo verifica se o elem_into da posição item descendentes + 2 • i < = tam 2 • 1 < = 8 . . V • o elemento da posição item descendentes encontrar a posição do menor elemento entre os descendentes {filhos e netos) m = posição do menor descendente do elemento da posição i m compara o elemento da posição i com o elemento da posição m heap{m) < heap{Q +heap{S) < heap{1) . . 12 < 28 + V . .troca
""5.
o 1
heap
2
4
3
5
6
7
8
9
10
tam
~I~I1_2~133_1~4_6~I1_4~12_a1~1_1~12_0~12_51~~1~I
0
i
[TI
verifica se o elemento da posição m é neto +m > = 4 • i 5 > = 4 • 1 + V + é neto, verificar as propriedades heap com o pai pai = mf.1 = 5/2 = 2 heap{pai) < heap{m) . . heap{2) < heap{S) 33 < 28+ F + elementos permanecem onde estão
14• operação Remoção do elemento de maior prioridade da lista de prioridades (heap min-max)
o 1
2
3
4
5
6
7
8
9
10
tam
0
Capítulo 5
o
Estrutura de dados do tipo lista de prioridades
estrutura heap min_max + o elemento de maior prioridade está na posição 2 ou 3 verWica qual o maior elemento + heap(2) > heap(3) + 33 > 46 + F elemento da posição 3 será removido elemento da última posição ocupada será copiado para a posição 3 e será descartado analisar as propriedades heap para o novo valor da posição 3
01234
5
678
9
10 1
tam
1
0
4
i
[I]
7
nivel = log) + 1 = 2 + nível par + nível máximo verifica se o elemento da posição i tem descendentes • 2 * i < "" tam 2 • 3 < = 7 . . V + o elemento da posição item descendentes encontrar a posição do maior elemento entre os descendentes (filhos e netos) m = posição do maior descendente do elemento da posição i m = 7 + compara o elemento da posição i com o elemento da posição m heap(m) > heap(Q + heap(l) > heap(3) 20 > 25 + F + elementos pem,anecem onde estão
15° operação Remoção do elemento de menor prioridade da lista de prioridades (heap min-max) 012345678
heap
l
9
112 133 25 114 128 1 171 20 1
10 1
tam
1
[D
4
7
estrutura heap min_max + o elemento de menor prioridade está na posição 1 elemento da posição 1 será removido elemento da última posição ocupada será copiado para a posição 1 e será descartado analisar as propriedades heap para o novo valor da posição 1
01234567
8
9
10 1
tam
1
0
4 nivel = log) + 1 = 1 + nivel ímpar + nível mínimo verWica se o elemento da posição i tem descendentes + 2 • i < = tam 2 • 1 < = 6 + V + o elemento da posição item descendentes encontrar a posição do menor elemento entre os descendentes (filhos e netos) m = posição do menor descendente do elemento da posição i m "" 4 • com para o elemento da posição i com o elemento da posição m heap(m) < heap(~ + heap(4) < heap(1) + 14 < 20 + v + troca
i
O]
227
228
Estruturas de dados 012345678
9
10 1
tam 1
i
[I] [TI
4
+
verifica se o elemento da posição m é neto m > "" 4 • i 4>=4•1 V é neto, verificar as propriedades heap com o pai pai=m/2=412=2 heap(pai) < heap(m) heap(2) < heap(4) 33 < 20. F . . elementos permanecem onde estão
+ +
lõo11011 1010010 0011100 J A V A
+
import java.util.Scanner; public class Heap_Min_Max {
li declarando o vetor com capacidade de no máximo 10 li números static int vet[]= new int[ll]; static in t tam; public static void main(String[] a r gs) {
Scanner entrada = new Scanner (System.in) ; int op, mp, num; tam = O; do System . out . println ("\nMENU DE OPÇÕES - HEAP Min_ • Max\n"); System . out . print ln ("1 - Inserir elemento na lista de p ri o ri dades") ; System . out . println ("2 - Consultar o eleme nto de • menor prioridade") ; System . out . println("3 - Consultar o elemento de • maio r prioridade"); System . out . println("4 - Remover o elemento de • menor prioridade"); System . out . println("5 - Remover o e l e me nto de • maior p ri o ridade") ; Syst em . out . println("6 - Consultar toda a lista" );
Capítulo 5
o
Estrutura de dados do tipo lista de prioridades
229
System. out. println ("7 - Sair") ; System . out.print("Digite sua opção : "); op = entrada.nextint() ; if (op < 1 11 op > 7) System. out. println ("Opção inválida! ! "); else if (op==l) {
// veriílca se ainda existe espaço dispo nivel .,. no vetor // para inserção do novo número if (tam = 3) if(vet[3J>vet[2]) ma x = 3; S ystem.out .println("O element o removi do : " +vet [max] ) ; vet [ma x] = ve t [ta m]; t am-- ; desce r (ma x);
else if ( o p==6) impressa o();
Capítulo 5
o
Estrutura de dados do tipo lista de prioridades
while(op!=7);
static void inserir_mm(int num , int i) vet[i] = num; subir(i );
static void subir(int i) int pai=
il2 ; li é o índice do possível pai II função 'mínimo'
li veri fica se o nó i encontra- se em um nive l minimo if (mínimo (i))
li ver i fica se o elemento de nive l minimo li é ma i or que o pa i i f (pai>=l) {
if(vet[i] > vet[pai]) {
trocar(i, pai); subir_max(pai) ; else subir_ min(i);
else
li verifica se o e l emento de nive l máx i mo li é menor qu e o pa i i f (pai>=l) {
if(ve t[ i] < vet[pa i]) {
t r ocar(i, pai); subir_ min (pa i) ; e l se subir_ma x(i) ;
231
232
Estruturas de dados
static void subir_min(int i) int avo= i/4;
// índice do possível avô
// verifica se o elemento é menor que o avô if(avo >= 1 && vet[i] < vet[avo]) trocar(i, avo); subir_min(avo);
static void subir_max(int i) int avo= i/4; // índice do possível avô // verifica se o elemento é maior que o avô if(avo >= 1 && vet[i] > vet[avo]) trocar(i, avo); subir_max(avo);
static int maior_prior() if (tam==l) re turn else if(tam > re turn else re turn
1 ,·
2 && vet[3]> vet[2] ) 3; 2 ,·
static void descer(int i) if (minimo ( i) ) descer_min (i); else descer_max(i);
static boolean minimo(int i)
Capítulo 5
o
Estrutura de dados do tipo lista de prioridades
int nivel = ((int) (Math.log(i)IMath . log(2))) + l ; if(nivel % 2 == O) return false; else return true;
static void descer_min(int i) if (2*i
vet[m]) {
t rocar (i, m); if(m >= 4*i) int p = ml2 ; li pé o pai if(vet[p] < vet[m]) trocar (p, m) ; descer_min (m) ;
static int min_descendente(int i)
li re torna índice do menor dos descendentes li e ntr e filh o s e ne t os d o e l e me nt o i int m=O; li índice do menor elemento if (2*i =l)
Capítu lo 5
o
Estrutura de dados do tipo lista de prioridades
if(vet[i] > vet[pai]) {
trocar(vet, i, pai); subir_ max(vet , pai); else subir_min(vet, i);
else
II verifica se o e l emen t o de n í ve l máx i mo li é meno r que o p ai if (pai>=l) {
if(vet[i] < vet[pai]) {
trocar(vet, i, pai); subir_ min(vet, pai); else subir_ max(vet, i);
void inserir_ mm(in t v e t [], int
num, int
v et [i] = num; subir(vet , i);
int
ma i o r _prior(in t v e t [], int tam) i f (tam==l) ret urn e l se if( tam ret urn els e ret urn
1·,
> 2 && vet [3] > v e t [2]) 3; 2 ,·
i)
237
238
Estruturas de dados
int min_descendente(int vet[] ,
int i, int tam)
li retorna índice do menor dos descendentes li entre filhos e netos do elemento i int m=O; li índice do menor elemento if(2*i > op; ( op < 1 1 1 op > 4) cout num; pos=funcao_ .,. hashing(num); inserir(tabela, pos, num); break; case 2 : mostrar_ hash(tabel a ); getch () ; break ; case 3 : cout vizinho do 4 (vértice 1)
[TI3-[TI3-[rry[ITJ []B-,-[IIJ [TI3-[IG-[ID
ill3-Cil3+ITD w3-ITD como o vértice 1 já foi marcado e todos os vizinhos do 4 já foram verificados na recursividade, volta-se para o vértice 5
próximo vértice: 2" vizinho do 5 (vértice 1)
[TI3-[TI3-[rry[ITJ []B-,-[IIJ [TI3-[IG-[ID
ill3-Cil3+ITD w3-ITD como o vértice 1 já foi marcado e todos os vizinhos do 5 já foram verificados na recursividade, volta-se para o vértice 1
próximo vértice: 2" vizinho do 1 (vértice 4)
o 1
[TI3-[TI3-[rry[ITJ
2
[]B-,-[IIJ [TI3-[IG-[ID
3 4 5
ill3-Cil3+ITD w3-ITD como o vértice 4 já foi marcado, busca-se o próximo vértice próximo vértice: 3'> vizinho do 1 (vértice 3)
381
382
Estruturas de dados
[]G-+[IT3+[il3-+CIT:J
w::3-0::0 []]3--[]]3--[ITJ []G-+[IG+[ITJ []]3--[ITJ como o vértice 3 já foi marcado, busca-se o próximo vértice próximo vértice: 42 vizinho do 1 (vértice 2)
[]G-+[IT3+[il3-+CIT:J
w::3-0::0
[]]3--[]]3--[ITJ []G-+[IG+[ITJ []]3--[ITJ como o vértice 2 já foi marcado e todos os vizinhos do 1 já foram verificados, a busca termina
lõo11011 1010010 0011100 J
imp o r t
j ava .util . Scanner;
A V A
p ub l ic c l ass b uscap {
publ ic static c l ass ve r tice {
i n t n um; v e r t i ce p r o x; p ub li c stat i c c l ass listaadj p ub li c ve r t i ce li stav; publ i c stat i c c l ass queue i nt n u mv; que u e prox ; publ ic s tat ic v oid empilha r ( i n t n) {
q ue u e novo = new que u e (); n ,· novo . numv n ov o . prox = pilha ;
Capítulo 8
o
Algoritmos em grafos
383
pilha = novo ; public static void desempilhar(int v) {
if (pilha. numv==v) {
pilha= pilha.prox;
static queue pilha
null; // pilha p/armazenar // vertices // visitados static Scanner entrada new Scanner(System.in); static int marcado[]; // vetor que armaze n a // se vértice for // marcado static listaadj Adj[]; // lista de adjacen c i as // entre / / vértices public static void main(String args[] ) vertice novo; int tam , org, dest , op, num, tipo ; String menu; System . out . println ("\n Tipo do grafo (1- n ã o • orientado, 2 - orientado : "); tipo= entrada .nextint() ; System . out . println ("\n Digite número de v értices • do grafo : "); tam = entrada .nextint() ; // alocação de memória Adj = n e w listaad j [tam+ l] ; marcado = new int [tam+ l]; // inicialização de v a ri á veis for(int i = 1; i (u, v) novo= new vertice(); novo. num = dest; II inserindo vértice adjacente a vértice "org" li na lista de adjacencias novo.prox = Adj[org] . listav; Adj[org] .listav = novo; if (tipo==l) {
li inserindo (v,u) novo= new vertice(); novo. num = org; li inserindo vértice adjacente a II vértice "org" na li lista de adjacencias novo . prox = Ad j[dest] . listav; Adj[dest] .listav = novo; }
li proxima entrada System.out . print("\n Arestas do grafo : ._. VérticeOrigem(-1 para parar):"); org = entrada . nextint(); System. out .print ("\n Arestas do grafo : ._. VérticeDestino (- 1 para parar) : "); dest = entrada .nextint (); do "\nl-Busca em profundidade"+ "\n2 - Mostrar lista de adjacencias"+ "\n4-Sair "+ "\nDigite sua opcao : " System . out . print(menu); op = ent r ada . nextint();
menu
Capítulo 8
o
A lgoritmos em grafos
385
switch(op) {
case 1: System.out.print("Digite um .,. vértice de partida da busca : ") ; num= entrada.nextint(); System . out . print(" "+num); buscaprof(Adj, tam, num) ; for (int i = 1; i > op; i f (op==l) {
cout > num; cout prox; return vert; cout p r ox;
void mostrar_Adj(listaadj Adj[] , int vertice *v ; for(int i=l; i
tam)
dist[1) + peso (1 , 2) oo > 0 + 2 V dist[x) = dist[w) + peso (w, x) dist[2) = dist[1) + peso (1 , 2) dist[2) O + 2 2
=
3
distâncias
o dist
2
o
=
O tamanho da lista é diferente de O? Sim Então é removido da lista o vértice com menor distância
w= 2 vizinhos de 2: 6, 5, 3, 1
2
3
4
5
6
1001001001
7
410
Estruturas de dados
Lista de prioridades: 3 4 5 6 ILUSTRAÇÃO
X=6 dist[x] > dist[w] + peso (w, x) dist[6] > dist[2] + peso (2, 6) 7 >2 +4 V dist[x] = dist[w] + peso (w, x) dist[6] = dist[2] + peso (2, 6) dist[6] = 2 + 4 = 6 X=5 dist[x] > dist[w] + peso (w, x) dist[5] > dist[2] + peso (2, 5) 00 >2 +3 V dist[x] = dist[w] + peso (w, x) dist[5] = dist[2] + peso (2, 5) dist[5] = 2 + 3 = 5 X=3 dist[x] > dist[w] + peso (w, x) dist[3] > dist[2] + peso (2, 3) oo > 2+9 V dist[x] = dist[w] + peso (w, x) dist[3] = dist[2] + peso (2, 3) dist[3] = 2 + 9 = 11 X= 1 dist[x] > dist[w] + peso (w, x) dist[1 ] > dist[2] + peso (2, 1) O > 2 +2 F
distâncias
o dist
1
2
o
2
3
4
5
looloolool
6
6
distâncias
o dist
1
2
o
2
3
4
loolool
5
6
5
6
distâncias
o dist
1
2
3
o
2
11
4 1
00 1
5
6
5
6
distâncias
o dist
1
2
3
4
5
6
o
2
11
00 1 1
5
6
5
6
5
6
O tamanho da lista é diferente de 07 Sim Então é removido da lista o vértice com menor distância w= 5 vizinh os de 5: 6, 4, 3, 2
Lista de prioridades: 3 4 6 ILUSTRAÇÃO
X=6 dist[x] > dist[w] + peso (w, x) dist[6] > dist[5] + peso (5, 6) 6 >5 +1 F
distâncias
o dist
1
2
3
o
2
11
4 1
00 1
Capítulo 8 X=4 dist[x] > dist[w] + peso (w, x) dist[4] > dist[5] + peso (5, 4) oo>5 + 3 V dist[x] = dist[w] + peso (w, x) dist[4] = dist[5] + peso (5, 4) dist[4] = 5 + 3 = 8 X=3 dist[x] > dist[w ] + peso (w, x) dist[3] > dist[5] + peso (5, 3) 11 > 5+4 V dist[x] = dist[w] + peso (w, x) dist[3] = dist[5] + peso (5, 3) dist[3] = 5 + 4 = 9 X=2 dist[x] > dist[w] + peso (w, x) dist[2] > dist[5] + peso (5, 2) 2> 5 +3 F
o
Algoritmos em grafos
distâncias
o dist
1
2
3
4
5
6
o
2
11
8
5
6
distâncias
o dist
1
2
3
4
5
6
o
2
9
8
5
6
distâncias
o dist
1
2
3
4
5
6
o
2
9
8
5
6
O tamanho da lista é diferente de O? Sim Então é removido da lista o vértice com menor distância w= 6 vizinh os de 6: 5, 3, 2, 1 Lista de prioridades: 3 4
ILUSTRAÇÃO
X=5 dist[x] > dist[w] + peso (w, x) dist[5] > dist[6] + peso (6, 5) 5>6+ 1 F X= 3 dist[x] > dist[w] + peso (w, x) dist[3] > dist[6] + peso (6, 3) 9>6+3 F X=2 dist[x] > dist[w] + peso (w, x) dist[2] > dist[6] + peso (6, 2) 2>6+ 4 F X= 1 dist[x] > dist[w] + peso (w, x) dist[1] > dist[6] + peso (6, 1) 0>6+7 F
distâncias
o dist
1
2
3
4
5
6
o
2
9
8
5
6
distâncias
o dist
1
2
3
4
5
6
o
2
9
8
5
6
5
6
5
6
1
1
1
1
distâncias
o dist
1
2
o
2
1
3 1
9
4 1
8
1
distâncias
o dist
1
2
3
4
5
6
o
2
9
8
5
6
411
412
Estruturas de dados
O tamanho da lista é diferente de O? Sim Então é removido da lista o vértice com menor distância w = 4 vizinhos de 4: 5, 3
fJr
ILUSTRAÇÃO
Lista de prioridades: 3 X=5 dist[x] > dist[w] + peso (w, x) dist[5] > dist[4] + peso (4, 5) 5 > 8+3 F X=3 dist[x] > dist[w] + peso (w, x) dist[3] > dist[4] + peso (4 , 3) 9>8+5 F
distâncias
o
o
dist
2
3
4
5
6
2
9
8
5
6
distâncias
o
o
dist
2
3
4
5
6
2
9
8
5
6
O tamanho da lista é diferente de O? Sim Então é removido da lista o vértice com menor distância w = 3 vizinhos de 3: 6, 5, 4, 2
Lista de prioridades: vazia ILUSTRAÇÃO
X=6 dist[x] > d ist[w] + peso (w, x) dist[6] > dist[3] + peso (3, 6) 6 >9 +3 F X= 5 dist[x] > d ist[w] + peso (w, x) dist[5] > d ist[3] + peso (3, 5) 5 > 9+4 F X=4 dist[x] > d ist[w] + peso (w, x) dist[4] > dist[3] + peso (3 , 4) 8 > 9+5 F X=2 dist[x] > dist[w] + peso (w, x) dist[2] > d ist[3] + peso (3, 2) 2 > 9+9 F
distâncias
o dist
1
2
3
4
5
6
o
2
9
8
5
6
distâncias
o dist
1
2
3
4
5
6
o
2
9
8
5
6
1
1
1
1
distâncias
o dist
1
2
3
4
5
6
o
2
9
8
5
6
1
1
1
1
distâncias
o dist
O tamanho da lista é düerente de O? Não
1
2
3
4
5
6
o
2
9
8
5
6
Capítulo 8
o
Algoritmos em grafos
413
Na implementação desse algoritmo, foi necessária a criação de uma lista de prioridades, cujo código também é apresentado nesta seção. Em seguida, o código do programa implementando o algoritmo de Dijkstra é apresentado. lõ0ll0ll
1010010 00lll00
J
A V A
i mport java .util . Scanner; public class ListaP r io r {
static static static public
int vet[]; Scanner entrada int tam; ListaPrior(int n)
new Scanner (System.in );
{
vet tam
new int [n+ l] ; O;
public static void inserir(int num, int d ist[]) int ind; if(tam < vet . length-1 ) {
tam++ ; ind=tam; while (ind> l && dist[vet[ Pai( ind)]l> ._. dis t [num] ) vet[ ind] =vet[Pai(ind)] ; ind=Pai (ind); vet[ind] = num;
public static int Pai (int x) { return x l2 ; public stat ic void heap_fica ( int i , int qtde , i nt dist [] ) {
int f _ esq, f _ dir , menor, a ux; men o r = i; if (2*i+l < = qtde)
li o nó que está sendo ana li sado tem li filh o s pi esque rda e di re ita f _ esq = 2 *i ; f_d ir = 2*i+l; i f (dist[vet[f_e sq]] < dist[vet [f_dir]] &&
414
Estruturas de dados
dist[vet[f_esq]J < dist[vet[i]J) menor = 2*i; else if (dist[vet[f_dir]J < ._. dist[vet[f_esq]J && dist [vet [f_dir]] < dist [vet [i]] ) menor = 2*i+l; else if (2*i = 1; i --) heap_fica(i , tam , dist) ; public static int remover(int dist[J) {
if(tam==O) System.out.println("Lista vaz i a !"); else {
int menor_prior=vet[l]; vet [ 1] =vet [tam]; tam--; he ap _ fi c a ( 1, tam, di s t) ; return menor_prior; return O; public static void imprimir() {
for(int i=l; i