Algoritmos de Junção – IndexNL e Sort Merge Join AULA 19 Profa. Sandra de Amo GBC053 – BCC.
Merge Sort
-
Upload
ana-paula-simiqueli -
Category
Documents
-
view
238 -
download
0
description
Transcript of Merge Sort
UNIVERSIDADE FEDERAL DO ESPIRITO SANTO
CENTRO DE CIENCIAS AGRARIAS
DEPARTAMENTO DE COMPUTAÇÃO
CURSO DE SISTEMAS DE INFORMAÇÃO
DISCIPLINA DE PROGRAMAÇÃO I
MERGESORT
ALEGRE
2012
ANA PAULA SIMIQUELI BORGES
DILHERMANDO VIEIRA STOCK
TALITA CUMI GOUVEIA ROZADO
THAISLANE ROSA DE SOUZA COSTA
MERGESORT
Trabalho apresentado à disciplina de Programação I sob orientação da professora Simone Dornellas
ALEGRE
2012
Sumário 1 Introdução .................................................................................................................................. 5
2 O algoritmo................................................................................................................................. 6
2.1 Introdução ao MergeSort .................................................................................................... 6
2.2 Significado do MergeSort .................................................................................................... 6
2.3 Classificação ........................................................................................................................ 6
2.4 Aplicando Dividir para conquistar no MergeSort ................................................................ 7
2.5 Complexidade ...................................................................................................................... 7
2.6 Vantagens e Desvantagens ................................................................................................. 8
3 Funcionamento do MergeSort ................................................................................................... 9
3.1 Pseudocódigo ...................................................................................................................... 9
3.2 Código em Pascal .............................................................................................................. 10
4. Parte Dois ................................................................................................................................ 12
4.1 O Problema ........................................................................................................................ 12
4.2 Solução .............................................................................................................................. 13
5 Referências bibliográficas ........................................................................................................ 24
Índice de Ilustrações
Figura 1: Funcionamento do algoritmo mergesort. ...................................................................... 7
1 Introdução
Ordenação é o ato de se colocar os elementos de uma sequência de informações, ou
dados, em uma ordem predefinida. O termo técnico em inglês para ordenação é sorting,
cuja tradução literal é "classificação".
Um algoritmo de ordenação na área de computação é um algoritmo que coloca os
elementos de uma dada sequência em certa ordem. Existem vários algoritmos
destinados a este fim, a maioria deles baseado na ideia de inserção, seleção e
permutação. Existem métodos simples como Insertion sort , Selection sort e Bubble
sort e métodos sofisticados como quick sort, shell sort e merge sort. Neste trabalho
falaremos em especial sobre o Merge Sort.
2 O algoritmo
2.1 Introdução ao MergeSort
Ainda existe uma discussão sobre o assunto, mas apareceram evidências de que o
algoritmo foi proposto por John Von Neumann em 1945. A atribuição a ele veio de
Knuth, que argumentou no seu livro ‘Arte de Programação Computacional: Ordenando
e Procurando’ que Von Neumann foi o primeiro a descrever a ideia.
2.2 Significado do MergeSort
O processo de Seleção e junção são complementares porque:
Seleção: divide a lista em duas outras independentes.
Junção: une duas listas independentes em uma lista maior ordenada. Isso insinua que o
Mergesort consiste em duas chamadas recursivas e um processo de junção.
Então, Mergesort é um algoritmo recursivo, que é implementado dividindo uma
sequência original em pares de dados, ordena-as e depois as agrupa em sequências de
quatro elementos, e assim por diante, até ter toda a sequência dividida em apenas duas
partes.
Assim, sua ideia básica é que é muito fácil criar uma sequência ordenada a partir de
duas outras também ordenadas.
2.3 Classificação
- Ordenação por partição
O Mergesort é classificado como ordenação por partição, que parte do princípio de
"dividir para conquistar". Este princípio é uma técnica que foi utilizada pela primeira
vez por Anatolii Karatsuba em 1960 e consiste em dividir um problema maior em
problemas pequenos, e sucessivamente até que o mesmo seja resolvido diretamente.
Esta técnica realiza-se em três fases:
Divisão: o problema maior é dividido em problemas menores e os problemas menores
obtidos são novamente divididos sucessivamente de maneira recursiva.
Conquista: o resultado do problema é calculado quando o problema é pequeno o
suficiente.
Combinação: os resultados dos problemas menores são combinados até que seja obtida
a solução do problema maior. Algoritmos que utilizam o método de partição são
caracterizados por serem os mais rápidos dentre os outros algoritmos pelo fato de sua
complexidade ser, na maioria das situações, O(nlogn).
2.4 Aplicando Dividir para conquistar no MergeSort
Dividir: dividir a lista em duas listas com cerca da metade do tamanho.
Conquistar: dividir cada uma das duas sublistas recursivamente até que tenham tamanho
um.
Combinar: fundir as duas sublistas de volta em uma lista ordenada.
Sendo estável na maioria de suas implementações, onde estas podem ser iterativas ou
recursivas. Sua desvantagem é o fato de utilizar uma estrutura auxiliar, ocupando o
dobro de memória.
É interessante destacar suas características em cima do paradigma de "divisão para
conquista":
Dividir: se a sequência tiver mais de um elemento, divida em duas partes.
Conquistar: ordene cada subsequência em separado usando mergesort.
Combinar: junte as duas subsequências em uma sequência ordenada.
A operação de fusão merge, do mergesort, é muito utilizada na busca online, aonde os
dados chegam de blocos em blocos, são ordenados por qualquer método e depois
fundidos pela mesma. No entanto, esta abordagem pode demandar muito tempo e
espaço de armazenamento se os blocos recebidos forem pequenos em comparação com
os dados ordenados.
Figura 1: Funcionamento do algoritmo mergesort.
2.5 Complexidade
Primeiramente vamos definir o que é melhor, médio e pior caso para o MergeSort.
Melhor Caso – nunca é necessário trocar após comparações.
Médio Caso – há necessidade de haver troca após comparações.
Pior Caso – sempre é necessário trocar após comparações.
Para o MergeSort não tem tanta importância se o vetor está no melhor, médio ou pior
caso, porque para qualquer que seja o caso ele sempre terá a complexidade de ordem
n*logn, como pode ser verificado na tabela abaixo:
Melhor caso O(n log2 n)
Médio caso O(n log2 n)
Pior caso O(n log2 n)
Isso é pelo motivo de que o MergeSort independentemente em que situação se encontra
o vetor, ele sempre irá dividir e intercalar.
Na prática, é difícil (senão impossível) prever com rigor o tempo de execução de um
algoritmo ou programa.
O tempo vai depender de varias constantes, como por exemplo, o tempo de
processamento de cada computador, do algoritmo implementado.
2.6 Vantagens e Desvantagens
Vantagens:
- Útil para ordenação externa;
- Pior caso: O(n log2 n)
- Aplicações com restrição de tempo
- Fácil implementação
Desvantagens:
- Utiliza memória auxiliar
- Alto consumo de memória
Outras Informações
• Eficiente para ordenar listas:
3 Funcionamento do MergeSort
3.1 Pseudocódigo
MergeSort (vetor, Inicio, fim)
Se inicio < fim então
meio<-(inicio +fim) div 2
MergeSort (vetor, inicio, meio);
MergeSort (vetor, meio+1, fim);
Merge (vetor, inicio, meio, fim);
fim-se
Merge (vetor, inicio, meio, fim);
i<- inicio
j<- meio+1;
k<-1;
enquanto (i<= meio) e (j<=fim) faça
se vetor[i] < vetor [j] então
aux[k] <- vetor[i];
i <- i+1;
senao
aux[k] <- vetor[j];
j <- j+1;
fim-se
k<-k+1;
fim-enquanto
enquanto (i<= meio) faça
aux[k] <-vetor[i];
k<-k+1;
i<-i+1 ;
fim-enquanto
enquanto (j<= fim) faça
aux[k] <-vetor[j];
k<-k+1;
j<-j+1;
fim-enquanto
para k<-ini ate fim do
vetor[k]<-aux[k]
fim-para
3.2 Código em Pascal
program MergeSort;
uses crt;
type
vetor= array[1..10] of integer;
procedure merge(var v:vetor; ini,meio,fim: integer);
var
aux:vetor;
i,j,k: integer;
begin
i := ini;
j := meio + 1;
k := ini;
while ((i <= meio) and (j <= fim)) do
begin
if (v[i] < v[j]) then
begin
aux[k] := v[i];
I := i + 1;
end
else
begin
aux[k] := v[j];
j := j + 1;
end;
k := k + 1;
end;
while (i <= meio) do
begin
aux[k] := v[i];
k := k + 1;
i := i + 1;
end;
while (j <= fim) do
begin
aux[k] := v[j];
k := k + 1;
j := j + 1;
end;
for k := ini to fim do
v[k] := aux[k];
end;
procedure mergesort(var v:vetor; i, f:integer);
var
m: integer;
begin
if i<f then
begin
m:=(i+f) div 2;
mergesort(v, i, m);
mergesort(v, m+1, f);
merge(v,i,m, f);
end;
end;
var
i:integer;
vetorzin:vetor;
begin
for i:=1 to 10 do
readln(vetorzin[i]);
mergesort(vetorzin, 1, 10);
for i:=1 to 10 do
writeln(vetorzin[i]);
readkey;
end.
4. Parte Dois
4.1 O Problema
Os juízes de uma maratona de surf precisam da sua ajuda. Os juízes por muito tempo
utilizaram um programa chamado de quebra_galho que utilizava vetores de registros
para armazenar as notas e outras informações dos participantes da maratona. Com o
passar do tempo notaram que toda vez que o computador era desligado as informações
dos participantes eram perdidas e se tornou muito custoso ter que digitar todas as
informações todas as vezes que precisavam trabalhar com os dados dos maratonistas,
além disso a maratona de surf vem ganhando reconhecimento e sendo cada vez mais
disputada. Os juízes estão felizes com o aumento do número de participantes, mas agora
o programa quebra_galho não atende as novas necessidades que surgiram. Para ajudar
os juízes o seu grupo deve elaborar um programa em pascal para facilitar a vida dos
juízes na gerência dos participantes da maratona. Agora eles querem uma solução que
armazene os dados sem perdê-los toda vez que o computador for desligado. Para isso,
seu grupo deve armazenar as informações dos maratonistas em arquivo. O programa
deve ser modularizado e oferecer as seguintes opções para os juízes:
(1) Abrir um arquivo existente com as informações dos maratonistas;
- o juiz deve especificar o nome do arquivo a ser aberto;
- caso não exista o arquivo, deve-se criar um novo arquivo em branco.
(2) Cadastrar novos participantes;
- o juiz deve especificar os dados de um novo maratonista.
- caso o arquivo ainda não tenha sido especificado o programa deve chamar a opção
1 antes de executar o cadastro.
(3) Exibir todas as informações dos maratonistas;
- este módulo deve listar todas as informações para todos os maratonistas, armazenadas
em arquivo.
(4) Ordenar os maratonistas por nota;
- este módulo deve ler todas as informações do arquivo e armazená-las em um vetor
(memória primária). Ordenar o vetor de acordo com a nota obtida pelo maratonista
utilizando o algoritmo de ordenação do grupo.
(5) Exibir os três primeiros vencedores;
- este módulo deve exibir as três primeiras posições do vetor já ordenado.
(6) Realizar busca por nome;
- o juiz deve especificar o nome do maratonista a ser buscado;
- se o nome for encontrado:
- este módulo deve exibir todas as informações referentes ao maratonista procurado e a
sua classificação. A classificação é a posição que ele for encontrado no vetor ordenado.
- caso o nome não seja encontrado:
- este módulo deve informar ao juiz que o nome não foi encontrado.
- OBS.: implementar a busca binária, o vetor deve estar ordenado quando este módulo
for ativado!
(7) Sair do programa.
- o programa deve ser finalizado quando o juiz escolher esta opção.
O Programa deve possuir as opções de (1) a (6) construídas de forma modularizada,
além disso o programa deve sempre perguntar ao juiz qual opção ele deseja realizar com
a seguinte frase: “Escolha uma das opções abaixo:” (as opções devem ser listadas para
que o juiz possa fazer a sua escolha). Os juízes decidiram que precisam armazenar as
seguintes informações para cada maratonista (lembre-se dos registros):
- nome;
- sobrenome;
- idade;
- cpf;
- estado civil;
- quantidade de ondas;
- nota;
- email;
4.2 Solução
program Maratona_de_Surf;
uses WinCrt, crt;
type
dados = record //criei meu tipo para manipular as informações
nome:string;
sobrenome:string;
idade:integer;
cpf:string[15];
estado_c:string;
n_ondas:integer;
nota: real;
email: string;
posi:integer;
end;
arquivo = File of dados; //um tipo do arquivo tipado do meu registro
vetor=array[1..100] of dados; // um vetor do tipo do meu registro
var
arq:arquivo;
op:char;
{--------------------------------------------------1-----------------------------------------------}
procedure abrir; //abrir o arquivo.
var
nome_arq:string;
Begin
Write ('Digite o nome do arquivo: ');
Readln (nome_arq);
nome_arq:=nome_arq+'.dat';
Assign (arq, nome_arq); {faz o assinalamento}
{$I-}
Reset (arq); {tenta abrir o arquivo}
If IOresult <> 0 then
Rewrite (arq);
{$I+}
clrscr;
end;
{---------------------------------------------adicional---------------------------------------------}
procedure erro(var aux:char); // para tratar de usuarios engraçadinhos
begin
while(( aux<>'S')and (aux<>'N')) do
begin
writeln('Opcao Invalida');
writeln('Pressione S para sim e N para nao');
readln(aux);
aux:=upcase(aux);
end;
clrscr;
end;
{---------------------------------------------2------------------------------------------------------}
procedure novo_cad;
var
aux, conf:char;
aux_no:string;
cadr:dados;
begin
abrir;
aux:='S';
while aux='S' do //repetir quantas vezes ele quiser
begin
repeat //Repetir até os dados estarem certos.
write('Nome do participante: ');
readln(aux_no);
cadr.nome:=upcase(aux_no); //salva o nome todo em maiúsculo
write('Sobrenome do participante: ');
readln(aux_no);
cadr.sobrenome:=upcase(aux_no);
write('CPF do participante: ');
readln(cadr.cpf);
write('Estado Civil do participante: ');
readln(cadr.estado_c);
write('Quantidade de ondas: ');
readln(cadr.n_ondas);
write('Nota do participante: ');
readln(cadr.nota);
write('Email do Participante: ');
readln(cadr.email);
cadr.posi:=1;// para salvar a colocação do candidato após a ordenação.
writeln();
writeln('Os dados estao Corretos?');
writeln();
writeln('Pressione S Para confirmar e N para Alterar os Dados');
readln(conf);
conf:=upcase(conf);
if (( conf<>'S')and (conf<>'N')) then
erro(conf);
clrscr;
writeln();
if conf='S' then {perguntar se os dados estão certos}
begin
seek(arq,filesize(arq)); {seek posiciona o vetor, e filesize é para
identificar quantos registros tem no arquivo, então vai colocar no fim}
write(arq,cadr);
end
else
clrscr;
writeln('Por favor, digite os dados do participante novamente.');
until conf='S'; {vai repetir até tudo está certo}
clrscr;
writeln();
writeln('Deseja adicionar dados de outro participante? (s/n)');
readln(aux);
aux:=upcase(aux);
if (( aux<>'S')and (aux<>'N')) then
erro(aux);
clrscr;
end;
close(arq);
exit;
end;
{-------------------------------------------------3------------------------------------------------}
procedure leitura;
var
cadr:dados;
aun:integer;
begin
abrir;
writeln('Lista dos Participantes:');
aun:=1;
while not(eof(arq)) do
begin
read(arq,cadr); {lendo o arquivo}
writeln('Participante ', aun);
writeln('Nome Completo: ',cadr.nome, #32,cadr.sobrenome );
writeln('CPF: ', cadr.cpf);
writeln('Estado Civil: ', cadr.estado_c);
writeln('Quantidade de ondas: ', cadr.n_ondas);
writeln('Nota: ', cadr.nota:2:2);
writeln('Email do Participante: ', cadr.email);
inc(aun);
writeln();
end;
close(arq);
writeln('Todos os participantes foram listados');
writeln('Precione [ENTER] para vontar ao Menu Principal');
readkey;
clrscr;
exit;
end;
{-------------------------------------------------4-----------------------------------------------}
procedure merge(var v: vetor; ini,meio,fim: integer);
var
aux:vetor;
i,j,k: integer;
begin
i := ini;
j := meio + 1;
k := ini;
while ((i <= meio) and (j <= fim)) do
begin
if ((v[i].nota) > (v[j].nota)) then
begin
aux[k] := v[i];
inc(i);
end
else
begin
aux[k] := v[j];
inc(j);
end;
inc(k);
end;
while (i <= meio) do
begin
aux[k] := v[i];
inc(k);
inc(i);
end;
while (j <= fim) do
begin
aux[k] := v[j];
inc(k);
inc(j);
end;
for k := ini to fim do
v[k] := aux[k];
end;
procedure mergesort(var v: vetor; i, f:integer);
var
m: integer;
begin
if i<f then
begin
m:=(i+f) div 2;
mergesort(v, i, m);
mergesort(v, m+1, f);
merge(v,i,m, f);
end;
end;
{prodecure principal da ordenação}
procedure ordenar;
var
i, fim: integer;
cadr:dados;
vet_ord:vetor;
begin
i:=0; //ajudar na manipulação de dados.
reset(arq); {passando pro vetor}
while not(eof(arq)) do
begin
inc(i); // pra garantir que o vetor vai começar de 1
read(arq,cadr);
vet_ord[i]:=cadr;
end;
close(arq);
fim:=i;
mergesort(vet_ord, 1, i); {chama o metodo de odenação}
for i:=1 to fim do {salva a posição}
vet_ord[i].posi:=i;
Rewrite (arq); //apaga o arquivo para salvar ele ordenado.
i:=1;
while i<fim+1 do
begin
cadr:=vet_ord[i];
write(arq,cadr);
inc(i);
end;
close (arq);
clrscr;
exit;
end;
{--------------------------------------------------5----------------------------------------------------}
procedure exibir;
var
i:integer;
cadr:dados;
begin
ordenar;
writeln('Listagem dos 3 primeiros colocados:');
reset(arq);
for i:=1 to 3 do
begin
read(arq,cadr); {lendo o arquivo}
writeln(i,' colocado(a): ',cadr.nome, #32,cadr.sobrenome );
end;
close(arq);
readkey;
clrscr;
writeln('Precione [ENTER] para voltar ao Menu Principal');
readkey;
clrscr;
exit;
end;
{------------------------------------------------6---------------------------------------------}
procedure busca;
var
vetor_nom:vetor;
i, j,k,ini, meio, fim:integer;
cadr, aux:dados;
opi:char;
achou:boolean;
bus:string;
begin
ordenar;
i:=0; //ajudar na manipulação de dados.
reset(arq); {passando pro vetor}
while not(eof(arq)) do
begin
inc(i); // pra garantir que o vetor vai começar de 1
read(arq,cadr);
vetor_nom[i]:=cadr;
end;
close(arq);
k:=i;
//Ordenando os nomes
for i:= k downto 2 do
for j:=1 to i-1 do
if (vetor_nom[j].nome > vetor_nom[j+1].nome) then
begin
aux := vetor_nom[j];
vetor_nom[j] := vetor_nom[j+1];
vetor_nom[j+1] := aux;
end;
writeln('Informe o nome do Participante que deseja buscar: ');
readln (bus); //jogar upcase em todos nomes
bus:=upcase(bus);
opi:='S';
while opi='S' do
begin
ini:=1;
fim:=k;
achou:=false;
repeat
meio:=(ini+fim) div 2;
if (bus=vetor_nom[meio].nome) then
begin
achou:= true;
ini:=fim+1;
end
else if (bus<vetor_nom[meio].nome) then
fim:=meio-1
else
ini:=meio+1;
until (ini>fim);
if achou=true then
begin
writeln ('O participante ', bus, ' está na ', vetor_nom[meio].posi, '° colocacao
');
writeln('abaixo os dados do calango');
writeln('Nome Completo: ',vetor_nom[meio].nome,
#32,vetor_nom[meio].sobrenome );
writeln('CPF: ', vetor_nom[meio].cpf);
writeln('Estado Civil: ', vetor_nom[meio].estado_c);
writeln('Quantidade de ondas: ', vetor_nom[meio].n_ondas);
writeln('Nota: ', vetor_nom[meio].nota:2:2);
writeln('Email do Participante: ', vetor_nom[meio].email);
end
else
write ('Desculpe, o nome do participante nao consta em nosso banco de
dados');
readkey;
clrscr;
write ('Deseja realizar uma nova busca? (s/n) ' );
readln(opi);
opi:=upcase( opi);
if opi='N' then
break;
writeln('Nome do Participante: ');
readln (bus);
bus:=upcase(bus);
end;
clrscr;
writeln('Precione [ENTER] para voltar ao Menu Principal');
readkey;
clrscr;
exit;
end;
procedure not_found(op:char);
begin
if(op<>'7') then
begin
writeln('Opcao invalida');
writeln('Precione [ENTER] Para voltar ao menu principal');
readkey;
end;
clrscr;
end;
{programa principal}
begin
TextBackGround(CYAN);
TextColor(WHITE);
clrscr;
op:='0';
while op<>'7' do
begin
Gotoxy(25,3);
writeln ('CONCURSO DE SURF');
writeln ();
writeln ();
writeln ('Escolha uma das opcoes abaixo:');
writeln ();
writeln ('(1) Abrir o Arquivo com as informacoes dos participaintes');
writeln ('(2) Cadastrar novos Participantes');
writeln ('(3) Exibir todas as informacoes.');
writeln ('(4) Organizar os participantes por nota.');
writeln ('(5) Exibir o top 3');
writeln ('(6) Realizar Busca');
writeln ('(7) Sair do Programa');
readln (op);
clrscr;
case op of
'1':abrir;
'2':novo_cad;
'3':leitura;
'4':begin
clrscr;
ordenar;
writeln('Participantes Ordenados');
writeln('Precione [ENTER] para retornar ao menu principal');
readkey;
clrscr;
end;
'5': exibir;
'6': busca;
else
not_found(op);
end;
end;
readkey;
end.
5 Referências bibliográficas
Merge Sort. Disponível em http://pt.wikipedia.org/wiki/Merge_sort Acesso em: 01 de
novembro. 2012.
Estudo do algoritmo de ordenação Mergesort, Disponível em
http://www.slideshare.net/luizaguerra/estudo-do-algoritmo-de-ordenao-mergesort
Acesso em: 01 de novembro. 2012.