merge sort

24
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

Upload: ana-paula-simiqueli

Post on 06-Aug-2015

238 views

Category:

Documents


0 download

DESCRIPTION

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

TRANSCRIPT

Page 1: 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

Page 2: Merge Sort

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

Page 3: Merge Sort

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

Page 4: Merge Sort

Índice de Ilustrações

Figura 1: Funcionamento do algoritmo mergesort. ...................................................................... 7

Page 5: Merge Sort

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.

Page 6: 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).

Page 7: Merge Sort

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.

Page 8: Merge Sort

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:

Page 9: Merge Sort

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

Page 10: Merge Sort

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];

Page 11: Merge Sort

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.

Page 12: Merge Sort

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.

Page 13: Merge Sort

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;

Page 14: Merge Sort

{--------------------------------------------------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';

Page 15: Merge Sort

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}

Page 16: Merge Sort

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;

Page 17: Merge Sort

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;

Page 18: Merge Sort

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.

Page 19: Merge Sort

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;

Page 20: Merge Sort

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;

Page 21: Merge Sort

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;

Page 22: Merge Sort

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;

Page 23: Merge Sort

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.

Page 24: Merge Sort

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.