Merge Sort

Post on 06-Aug-2015

238 views 0 download

description

Método de ordenação Merge Sort implementado na linguagem Pascal.

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.