TRABALHO Def Ord Est Dados Marcos Pacheco

17
MÉTODOS DE ORDENAÇÃO EM RUBY ALUNO: MARCOS ANTÔNIO PACHECO DOS SANTOS PROFESSOR: PROF DR. GLAUCO CARNEIRO O problema da classificação (ordenação) é descrito como se segue: Dada uma lista de elementos fornecidos como entrada em qualquer ordem arbitrária, esses elementos tendo um valor ordinal estabelecida, ou seja, uma sequência de agrupamento, reordená-los para que eles apareçam de acordo com o seu valor ordinal menor para o maior. Por exemplo, considere a seguinte lista de números como entrada: 5, 3, 7, 5, 2, 9 A saída ordenada que corresponde a esta entrada é: 2, 3, 5, 5, 7, 9. A seguir irei expor o trabalho solicitado citando métodos de ordenação clássicos e indicando suas características. Começarei pelo mais simples o bubble sort. BUBBLE SORT O algoritmo de ordenação bublesort tem os seguintes passos: Passo 1: Percorre todas as entradas da lista. Passo 2: Comparar cada entrada para todas as entradas sucessivas e troca se eles são fora de ordem. Passo 3: Repetir este processo num total de n - 1 vezes. O nome método da bolha deriva-se da maneira com que os maiores valores “afundam” em direção ao fim do vetor, enquanto os menores valores “borbulham” em direção à “superfície” ou início do vetor. Ou seja, este algoritmo varre o vetor, faz varredura(s) no vetor... Enquanto é realizada a varredura vai-se comparando os elementos vizinhos entre si... O algoritmo bubble sort pode fazer uma ou varias varreduras até que a estrutura esteja ordenada. Em cada fase desse método, um item de maior valor é deslocado para sua posição definitiva na lista ordenada. Então, se uma lista tem n itens, após a primeira etapa haverá n−1 itens a ordenar. Usando a mesma estratégia, após a segunda fase, termos n−2 itens, depois n−3 e assim sucessivamente até que reste um único item. A seguir o código em ruby do algoritmo bubble sort retirado do livro Science Programming Basics with Ruby 1 # Code for bubble sort 2 NUM_STUDENTS = 35 3 # Max grade of 100% 4 MAX_GRADE = 100 5 num_compare = 0 6 arr = Array.new(NUM_STUDENTS) 7 8 # Randomly put some final exam grades into arr 9 10 for i in (0..NUM_STUDENTS - 1) 11 arr[i] = rand(MAX_GRADE + 1) 12 end 13 14 # Output randomly generated array 15 puts "Input array:" 16 for i in (0..NUM_STUDENTS - 1) 17 puts "arr[" + i.to_s + "] ==> " + arr[i].to_s

Transcript of TRABALHO Def Ord Est Dados Marcos Pacheco

Page 1: TRABALHO Def Ord Est Dados Marcos Pacheco

MÉTODOS DE ORDENAÇÃO EM RUBY ALUNO: MARCOS ANTÔNIO PACHECO DOS SANTOS PROFESSOR: PROF DR. GLAUCO CARNEIRO O problema da classificação (ordenação) é descrito como se segue: Dada uma lista de elementos fornecidos como entrada em qualquer ordem arbitrária, esses elementos tendo um valor ordinal estabelecida, ou seja, uma sequência de agrupamento, reordená-los para que eles apareçam de acordo com o seu valor ordinal menor para o maior. Por exemplo, considere a seguinte lista de números como entrada: 5, 3, 7, 5, 2, 9 A saída ordenada que corresponde a esta entrada é: 2, 3, 5, 5, 7, 9. A seguir irei expor o trabalho solicitado citando métodos de ordenação clássicos e indicando suas características. Começarei pelo mais simples o bubble sort.

BUBBLE SORT O algoritmo de ordenação bublesort tem os seguintes passos: Passo 1: Percorre todas as entradas da lista. Passo 2: Comparar cada entrada para todas as entradas sucessivas e troca se eles são fora de ordem. Passo 3: Repetir este processo num total de n - 1 vezes. O nome método da bolha deriva-se da maneira com que os maiores valores “afundam” em direção ao fim do vetor, enquanto os menores valores “borbulham” em direção à “superfície” ou início do vetor. Ou seja, este algoritmo varre o vetor, faz varredura(s) no vetor... Enquanto é realizada a varredura vai-se comparando os elementos vizinhos entre si... O algoritmo bubble sort pode fazer uma ou varias varreduras até que a estrutura esteja ordenada. Em cada fase desse método, um item de maior valor é deslocado para sua posição definitiva na lista ordenada. Então, se uma lista tem n itens, após a primeira etapa haverá n−1 itens a ordenar. Usando a mesma estratégia, após a segunda fase, termos n−2 itens, depois n−3 e assim sucessivamente até que reste um único item. A seguir o código em ruby do algoritmo bubble sort retirado do livro Science Programming Basics with Ruby 1 # Code for bubble sort 2 NUM_STUDENTS = 35 3 # Max grade of 100% 4 MAX_GRADE = 100 5 num_compare = 0 6 arr = Array.new(NUM_STUDENTS) 7 8 # Randomly put some final exam grades into arr 9 10 for i in (0..NUM_STUDENTS - 1) 11 arr[i] = rand(MAX_GRADE + 1) 12 end 13 14 # Output randomly generated array 15 puts "Input array:" 16 for i in (0..NUM_STUDENTS - 1) 17 puts "arr[" + i.to_s + "] ==> " + arr[i].to_s

Page 2: TRABALHO Def Ord Est Dados Marcos Pacheco

18 end 19 20 # Now let's use bubble sort. Swap pairs iteratively as we loop through the 21 # array from the beginning of the array to the second-to-last value 22 for i in (0..NUM_STUDENTS - 2) 23 # From arr[i + 1] to the end of the array 24 for j in ((i + 1)..NUM_STUDENTS - 1) 25 num_compare = num_compare + 1 26 # If the first value is greater than the second value, swap them 27 if (arr[i] > arr[j]) 28 temp = arr[j] 29 arr[j] = arr[i] 30 arr[i] = temp 31 end 32 end 33 end 34 35 # Now output the sorted array 36 puts "Sorted array:" 37 for i in (0..NUM_STUDENTS - 1) 38 puts "arr[" + i.to_s + "] ==> " + arr[i].to_s 39 end 40 puts "Number of Comparisons ==> " + num_compare.to_s

A complexida do algortimo e fornecida na figura a seguir:

Obs: Um algoritmo de ordenação diz-se estável se preserva a ordem de registros de chaves iguais. Isto é, se tais registros aparecem na sequência ordenada na mesma ordem em que estão na sequência inicial. Esta propriedade é útil apenas quando há dados associados às chaves de ordenação(Wikipédia 2014)

Page 3: TRABALHO Def Ord Est Dados Marcos Pacheco

SELECTION SORT Seleção é o tipo mais simples de explicar e mais intuitiva. Imagine que você tem um baralho de cartas na sua mão, e eles têm números sobre eles. Se você queria classificá-los, um caminho mais fácil é simplesmente selecionar o menor número no baralho e trazê-lo até o topo. Agora repita o processo para todas as outras cartas do que a que você acabou de fazer. Se você repetir este processo até que toda a plataforma foi selecionada, você iria acabar com um baralho ordenada de cartões. Portanto Em uma ordenação por seleção, o elemento de valor mais baixo do vetor e escolhido e permutado (trocado) com o primeiro elemento dos elementos restantes, o de valor mais baixo é escolhido e trocado com o segundo elemento do vetor, e assim por diante, até que o vetor esteja ordenado. Ou seja, o selection sort (ordenação por seleção), tem como característica identificar, a cada nova iteração, a chave de menor (ou maior) valor na parte do vetor ainda não ordenada, e colocá-la em sua posição definitiva. O selection sort (do inglês, ordenação por seleção) é um algoritmo de ordenação baseado em se passar sempre o menor valor do vetor para a primeira posição (ou o maior dependendo da ordem requerida), depois o de segundo menor valor para a segunda posição, e assim é feito sucessivamente com os (n-1) elementos restantes, até os últimos dois elementos. Descrição: Seleciona sempre o menor elemento remanescente do conjunto não ordenado e move este elemento para sua posição correta Algoritmo:

Encontrar o menor elemento e trocar com o elemento na primeira posição do vetor

Encontrar o segundo menor elemento e trocar com o elemento na segunda posição do vetor e assim sucessivamente...

A seguir o código em ruby: 1 # Code for selection sort 2 # 35 students in our class

3 NUM_STUDENTS = 35 4 # Max grade of 100% 5 MAX_GRADE = 100 6 num_compare = 0 7 arr = Array.new(NUM_STUDENTS) 8 9 # Randomly populate arr 10 for i in (0..NUM_STUDENTS - 1) 11 # Maximum possible grade is 100%, keep in mind that rand(5) returns possible values 0-4, so we must add 1 to MAX_GRADE 12 arr[i] = rand(MAX_GRADE + 1) 13 end

14 15 # Output current values of arr 16 puts "Input list:" 17 for i in (0..NUM_STUDENTS - 1)

18 puts "arr[" + i.to_s + "] ==> " + arr[i].to_s 19 end

Page 4: TRABALHO Def Ord Est Dados Marcos Pacheco

20 21 # Now let's use a selection sort. We first find the lowest number in the 22 # array and then we move it to the beginning of the list 23 for i in (0..NUM_STUDENTS - 2)

24 min_pos = i 25 for j in (i + 1)..(NUM_STUDENTS - 1) 26 num_compare = num_compare + 1 27 if (arr[j] < arr[min_pos])

28 min_pos = j 29 end 30 end 31 # Knowing the min, swap with current first element (at position i)

32 temp = arr[i] 33 arr[i] = arr[min_pos] 34 arr[min_pos] = temp 35 end 36 37 # Now output the sorted array

38 puts "Sorted list:" 39 for i in (0..NUM_STUDENTS - 1) 40 puts "arr[" + i.to_s + "] ==> " + arr[i].to_s 41 end

42 43 puts "Number of Comparisons ==> " + num_compare.to_s

Fonte : Example 7-1. Code for selection sort pagina 89

O selecton sort é vantajoso quanto ao número de movimentos de registros, que é O(n) Deve ser usado para arquivos com elementos muito grandes, desde que o número de elementos a ordenar seja pequeno.

INSERTIO SORT Ordenação por inserção funciona, deixando o primeiro elemento sozinho e declará-la como um classificado lista de tamanho 1. O elemento seguinte é inserido na posição correta na nossa recém lista ordenada Continuamos levando cada novo elemento e inseri-lo na posição correta em nossa lista. Ao final, todas as nossas inserções resultam em uma única lista ordenada. O primeiro elemento a ser selecionado é o segundo elemento do vetor Se o elemento selecionado for menor que o elemento antes dele o elemento selecionado é trocado com seu antecessor A ideia é repetir este processo, sempre "empurrando o menor elemento para o início do grupo de elementos(vetor)

Page 5: TRABALHO Def Ord Est Dados Marcos Pacheco

Insertion sort, ou ordenação por inserção, é um simples algoritmo de ordenação, eficiente quando aplicado a um pequeno número de elementos. Em termos gerais, ele percorre um Vetor de elementos da esquerda para a direita e à medida que avança vai deixando os elementos mais à esquerda ordenados. O algoritmo de inserção funciona da mesma maneira com que muitas pessoas ordenam cartas em um jogo de baralho como o pôquer. A seguir o código em ruby

def insertion_sort(list)

(1..list.length - 1).each do |i|

value = list[i]

j = i - 1

while j >= 0 && list[j] > value do

list[j + 1] = list[j]

j -= 1

end

list[j + 1] = value

end

list

end

list = [9, 0, 45, 3, 6, 7, 20, 19, 5]

p list p insertion_sort(list)

O algoritmo de ordenação por inserção tem os seguintes passos: Passo 1: Considere apenas o primeiro elemento, e, portanto, a nossa lista é ordenada. Passo 2: Considere o próximo elemento; inserir o elemento para a posição adequada em na lista já classificada. Passo 3: Repita esse processo de adicionar um número novo para todos os números n.

O insertion sort é o mais interessante para arquivos com menos do que 20 elementos O método é estável Possui comportamento melhor do que o método bublesort que também é estável Sua implementação é tão simples quanto as implementações do bolha e seleção Para arquivos já ordenados, o método é O(n) O custo é linear para adicionar alguns elementos a um arquivo já ordenado

Page 6: TRABALHO Def Ord Est Dados Marcos Pacheco

Shell Sort O shellsort é uma proposta criada para acelerar o algoritmo insertion sort permitindo trocas entre elementos que estão afastados. Foi inventado por Donald L. Shell e se baseia na ideia de que podemos ordenar mais rápido se começarmos movendo as chaves distâncias maiores, para que eles cheguem mais rapidamente nas posições finais. Ideia do Algoritmo: Basicamente o algoritmo passa várias vezes pela lista dividindo o grupo maior em menores. Nos grupos menores é aplicado o método da ordenação por inserção(INSERTION SORT).

O método de seleção de valores para h proposto por Donald Shell foi h = n/2 em que n é o número de elementos do vetor Após fazer todas as trocas de elementos cuja distancia é h, o valor h deve ser reduzido: h = h/2 O algoritmo é repetido até que a distância de comparação h seja igual a um (h = 1). Veja um exemplo na figura a seguir:

(Kurth, 1973) propôs uma sequencia em que: h = 3*h+1 E a sequência gerada: 1, 4, 13, 40, 121, 364, 1093, 3280 Alguns pesquisadores famosos pesquisaram e propuseram metodos de seleção de valores para h Donald Shell, criador do SHELL SORT Donald Shell o próprio Knuth e Robert Sedgewick. A seguir uma figura da Wikipédia que indica mais valores propostos para h.

Page 7: TRABALHO Def Ord Est Dados Marcos Pacheco

A seguir o código em ruby do shell sort

def shellSort( array )

n = array.length

h = n/2

while h > 0

for i in (h...n)

Page 8: TRABALHO Def Ord Est Dados Marcos Pacheco

c = array[i]

j = i

while j >= h and c < array[j-h]

array[j] = array[j-h]

j = j-h

array[j] = c

end

end

h = (h/2.2).to_i

end

end

O shell sort é bom para ordenar um número moderado de elementos Quando encontra um arquivo parcialmente ordenado trabalha menos

MERGE SORT Este já é um algoritmo de ordenação mais elaborado. Neste caso os problemas são resolvidos separadamente. As soluções parciais são combinadas de modo a se obter uma solução para o problema original. O método é expresso por algoritmos recursivos São 3 passos: Dividir, Conquistar e Combinar Dividir o problema original em subproblemas menores Conquistar os subproblemas resolvendo-os recursivamente Combinar as soluções dadas aos subproblemas, compondo uma solução para o problema original A Ordenação por Intercalação (Merge Sort) criar uma seqüência ordenada a partir de duas outras já ordenadas; Se a lista é de tamanho 0 ou 1 então ela já está ordenada; Se não: Divida a lista aproximadamente na metade Ordene cada sub-lista recursivamente (chamando o próprio mergesort) Efetue o merge (intercala) nas duas sub-listas ordenadas Mergesort (ordenação por intercalação) divide o vetor de entrada em dois subvetores com metade do tamanho do vetor original (em caso de tamanho ımpar um dos subvetores terá um elemento a mais que o outro). Cada um dos subvetores e ordenado recursivamente. Os dois subvetores são intercalados em um vetor temporário. A seguir um exemplo deste processo.

Page 9: TRABALHO Def Ord Est Dados Marcos Pacheco

A complexidade do merge sort Complexidade é O(n log n) o que revela já ser melhor na maioria dos cenários em relação aos algoritmos citados anteriormente A seguir dois códigos em ruby def merge_sort(list) return list if list.size < 2 left = list[0, list.length/2] right = list[list.length/2, list.length] merge(merge_sort(left), merge_sort(right)) end def merge(left, right) sorted_list = [] until left.empty? || right.empty? sorted_list << (left[0] <= right[0] ? left.shift : right.shift) end sorted_list.concat(left).concat(right) p sorted_list end list = [9, 0, 45, 3, 6, 7, 20, 19, 5] p list p merge_sort(list)

---------------------------------- 1 # Code for insertion sort 2 # Declare useful constants

3 NUM_STUDENTS = 35 4 MAX_GRADE = 100 5 num_compare = 0 6 arr = Array.new(NUM_STUDENTS) 7 8 # Randomly populate arr 9

Page 10: TRABALHO Def Ord Est Dados Marcos Pacheco

10 for i in (0..NUM_STUDENTS - 1)

11 arr[i] = rand(MAX_GRADE + 1) 12 end 13 14 # Output randomly generated array

15 puts "Input array:" 16 for i in (0..NUM_STUDENTS - 1)

17 puts "arr[" + i.to_s + "] ==> " + arr[i].to_s 18 end

19 20 # Now let's use an insertion sort 21 # Insert lowest number in the array at the right place in the array 22 for i in (0..NUM_STUDENTS - 1) 23 # Now start at current bottom and move toward arr[i]

24 j = i 25 done = false 26 while ((j > 0) and (! done))

27 num_compare = num_compare + 1 28 # If the bottom value is lower than values above it, swap it until it 29 # lands in a place where it is not lower than the next item above it 30 if (arr[j] < arr[j - 1])

31 temp = arr[j - 1] 32 arr[j - 1] = arr[j] 33 arr[j] = temp 34 else

35 done = true 36 end 37 j = j - 1 38 end 39 end 40 41 # Now output the sorted array

42 puts "Sorted array:" 43 for i in (0..NUM_STUDENTS - 1)

44 puts "arr[" + i.to_s + "] ==> " + arr[i].to_s 45 end

46 puts "Number of Comparisons ==> " + num_compare.to_s

Page 11: TRABALHO Def Ord Est Dados Marcos Pacheco

RADIX SORT O radix sort é muito diferente dos outros. Os algoritmos de classificação que discutimos comparam o número inteiro com outros números na lista para, finalmente, tomar uma decisão quanto ao local onde um elemento pertence com base no seu número. O radix sort funciona através de triagem da lista por cada dígito consecutivo. A ideia é que, se classificar em primeiro lugar todas as unidades ou os dígitos em uma lista e, em seguida, classificar todos os dígitos de dezenas e assim por diante, em última instância, quando corremos para fora de dígitos, teremos uma lista ordenada.

O Radix sort é um algoritmo de ordenação rápido e estável que pode ser usado para

ordenar itens que estão identificados por chaves únicas. Cada chave é uma cadeia de caracteres ou número, e o radix sort ordena estas chaves numa ordem qualquer

relacionada com a lexicografia. Ou seja os registros a serem ordenados podem ter chaves bastante complexas, como por exemplo sequências de caracteres (lista telefônica) a ordenação é realizada via comparação de chaves. . A seguir o código em ruby 1 # Code for radix sort

2 NUM_STUDENTS = 35 3 MAX_GRADE = 100 4 arr = Array.new(NUM_STUDENTS) 5 6 # Randomly put some grades into the array *as strings* 7 for i in (0..NUM_STUDENTS - 1)

8 arr[i] = rand(MAX_GRADE + 1).to_s 9 end

10 11 # Output array and find the maximum number of digits in the generated array

12 puts "Input array: " 13 max_length = 0 14 for i in (0..NUM_STUDENTS - 1)

15 puts "arr[" + i.to_s + "] ==> " + arr[i] 16 if arr[i].length > max_length

17 max_length = arr[i].length 18 end 19 end

20 puts "Max length ==> " + max_length.to_s 21 22 # Add 0 padding based on the max length, simplifying the sort algorithm 23 for i in (0..NUM_STUDENTS - 1) 24 arr[i] = arr[i].rjust(max_length, "0") 25 end

26 27 # Now let's use a radix sort. Go through each digit and 28 # add each element to an array corresponding to the digits. 29 for i in (0..max_length - 1) 30 # Clear out and reset the bucket 31 buckets = Hash.new() 32 for j in 0..9

33 buckets[j.to_s] = Array.new() 34 end 35

Page 12: TRABALHO Def Ord Est Dados Marcos Pacheco

36 # Add each number to its respective digit bucket 37 for j in 0..NUM_STUDENTS - 1

38 num = arr[j] 39 digit = num[max_length - 1 - i] 40 buckets[digit].push(num) 41 end 42 # Flatten the buckets into a one-dimensional array

43 arr = buckets.values.flatten 44 end

45 46 # Now output the sorted array

47 puts "Sorted array:" 48 for i in (0..NUM_STUDENTS - 1) 49 puts "arr[" + i.to_s + "] ==> " + arr[i].to_s 50 end

A complexidade do radix sort é mostrada a seguir e comparada com outros algoritmos.

O radix sort é o Superior ao Quicksort mostrado mais abaixo somente para arquivos muito grandes. Por isso a principal vantegem é que ele é um método muito rápido para arquivos grandes comchaves aleatórias. A principal desvantagem do radix sort é o espaço extra requerido.

HEAP SORT Em muitas aplicações, uma característica importante que distingue os dados em uma certa estrutura é uma prioridade atribuída a cada um deles. Nessas aplicações, em geral , determinar repetidas vezes o dado de maior prioridade é uma operação importante. Em muitas aplicações, dados de uma coleção são acessados por ordem de prioridade A prioridade associada a um dado pode ser qualquer coisa: tempo, custo, etc, operações comuns (eficientes) Seleção do elemento com maior (ou menor) prioridade Remoção do elemento de maior (ou menor) prioridade Inserção de um novo elemento

• O heap sort Utiliza uma estrutura de dados (heap) para organizar a informação durante a execução do algoritmo.

• Um heap é uma estrutura de dados baseada em árvore binária que segue um critério (ou condição) bem-definido(a).

• Estruturalmente, deve ser uma árvore quase completa: – O último nível pode não conter os nós mais à direita.

Page 13: TRABALHO Def Ord Est Dados Marcos Pacheco

• Obs: pode ser utilizando também um heap binário mínimo Seu desempenho em pior cenário é praticamente igual ao desempenho em cenário médio. Alguns algoritmos de ordenação rápidos têm desempenhos espectacularmente ruins no pior cenário, quer em tempo de execução, quer no uso da memória. O Heapsort trabalha no lugar e o tempo de execução em pior cenário para ordenar n elementos é de O (n lg n). Lê-se logaritmo (ou log) de "n" na base 2. Para valores de n, razoavelmente grandes, o termo lg n é quase constante, de modo que o tempo de ordenação é quase linear com o número de itens a ordenar. Comparações no pior caso: 2n log2n + O(n) é o mesmo que 2n lgn + O(n) Trocas no pior caso: n log2n + O(n) é o mesmo que n lgn + O(n) Melhor e pior caso: O(n log2n) é o mesmo que O(n lgn) A seguir código em ruby

def heap_sort (list)

sl = []

heap = build_heap(list)

heap.size.times do

sl << heap.shift

heap = heapify(heap, 0)

end

sl.reverse

end

def left(i)

((i+1)*2)-1

end

Page 14: TRABALHO Def Ord Est Dados Marcos Pacheco

def right(i)

(i+1)*2

end

def heapify(h, root)

max = root

l, r = left(root), right(root)

if ( l < h.size && h[l] > h[max])

max = l

end

if ( r < h.size && h[r] > h[max])

max = r

end

if( root != max)

h[root], h[max] = h[max], h[root]

return heapify(h, max)

else

return h

end

end

def build_heap(list)

heap = list.clone

(((heap.size)-1)/2).downto(0) do |e|

heap = heapify(heap, e)

end

heap

end

list = [9, 0, 45, 3, 6, 7, 20, 19, 5]

p list p heap_sort(list)

O heap sort é um método de ordenação elegante e eficiente não necessita de nenhuma memória adicional e executa sempre em tempo proporcional a O(n lg(n)) Aplicações que não podem tolerar eventuais variações no tempo esperado de execução devem usar o heapsort.

QUICK SORT É um método de ordenação por troca. Entretanto, enquanto o bubblesort (bolha) troca pares de elementos consecutivos, o quicksort compara pares de elementos distantes, o que acelera o processo de ordenação. A versão original do método foi apresentada por C. A. R. Hoare, em 1960. É um algoritmo de troca do tipo divisão e conquista que resolve um determinado problema dividindo-o em três subproblemas, tais que: o primeiro subproblema é composto dos elementos menores ou iguais ao pivô, o segundo subproblema é o próprio pivô e o terceiro subproblema são os elementos maiores ou iguais ao pivô. O método consiste em alocar um determinado elemento em sua posição correta dentro da futura lista ordenada, produzindo uma partição da lista em três sub-listas: a) a sub-lista que contém todos os elementos que são menores ou iguais ao elemento alocado; b) a sub-lista formada somente pelo elemento alocado;

Page 15: TRABALHO Def Ord Est Dados Marcos Pacheco

c) a sub-lista que contém todos os elementos que são maiores ou iguais ao elemento alocado. A parte mais delicada deste método é relativa ao procedimento partição, o qual tem que rearranjar a lista A através da escolha arbitária de um item X da lista denominado pivô, de tal forma que ao final a lista A está particionada em uma parte esquerda com os elementos menores ou iguais a X e uma parte direita com elementos maiores ou iguais a X. Algoritmo para o particionamento: 1. Escolha arbitrariamente um pivô P. 2. Percorra o vetor a partir da esquerda até que A[i] >P. 3. Percorra o vetor a partir da direita até que A[j] ≤ P. 4. Troque A[i] com A[j]. 5. Continue este processo até os apontadores i e j se cruzarem. Como a escolha do pivô é crucial para um bom desempenho do algoritmo, as implementações usam métodos mais sofisticados para a sua escolha, sendo os mais populares: 1. Mediana ( A[left], A[(right+left) / 2], A[right] ) 2. Aleatório (left..right) Análise Seja C(n) a função que conta o número de comparações. Pior caso: C(n) = O(n2) O pior caso ocorre quando, sistematicamente, o pivô é escolhido como sendo um dos extremos de um arquivo já ordenado. Isto faz com que o procedimento Ordena seja chamado recursivamente n vezes, eliminando apenas um item em cada chamada. O pior caso pode ser evitado empregando pequenas modificações no algoritmo. Para isso basta escolher três itens quaisquer do vetor e usar a mediana dos três como pivô Melhor caso: C(n) = 2C(n/2) + n = n log n Esta situação ocorre quando cada partição divide o arquivo em duas partes iguais. Caso médio de acordo com Sedgewick e Flajolet: C(n) ≈ 1,386n log n – 0,846n, Isso significa que em média o tempo de execução do Quicksort é O(n log n). Vantagens: É extremamente eficiente para ordenar arquivos de dados. Necessita de apenas uma pequena pilha como memória auxiliar. Requer cerca de n log n comparações em média para ordenar n itens. Desvantagens: Tem um pior caso O(n2) comparações. Sua implementação é muito delicada e difícil: Um pequeno engano pode levar a efeitos inesperados para algumas entradas de dados. Até hoje o quick sort é considerado um dos métodos de ordenação mais eficientes A seguir seu código em ruby: def quick_sort(list) sl = list.clone

return sl if sl.size <= 1

pivot = sl.pop

left, right = sl.partition { |e| e < pivot }

quick_sort(left) + [pivot] + quick_sort(right)

end

Page 16: TRABALHO Def Ord Est Dados Marcos Pacheco

list = [9, 0, 45, 3, 6, 7, 20, 19, 5]

p list p quick_sort(list)

O quick sort é o algoritmo mais eficiente que existe para uma grande variedade de situações. O algoritmo é recursivo, o que demanda uma pequena quantidade de memória adicional. No Pior caso realiza O(n2) operações e o principal cuidado a ser tomado é com relação à escolha do pivô. A escolha do elemento do meio do arranjo melhora o desempenho quando o arquivo está total ou parcialmente ordenado. O pior caso tem uma probabilidade muito pequena de ocorrer quando os elementos forem aleatórios. Geralmente se usa a mediana de uma amostra de três elementos para evitar o pior caso. Usar inserção em partições pequenas melhora desempenho do algoritmo significativamente.

Conclusões Observações sobre os métodos são descritas por completo pelo professor Ítalo Cunha nas notas de aulas presentes em http://homepages.dcc.ufmg.br/~cunha/teaching/20121/aeds2/sortingcmp.pdf Observe: 1. Shellsort, quicksort e heapsort têm a mesma ordem de grandeza para arranjos de até 30 mil elementos 2. O quicksort é o mais rápido para todos os tamanhos aleatórios experimentados 3. A relação heapsort/quicksort se mantém constante para todos os tamanhos de entrada 4. A relação shellsort/quicksort aumenta com o tamanho da entrada 5. Para arquivos pequenos (500 elementos), o shellsort é mais rápido que o heapsort (e vice versa) 6. Inserção é o método mais rápido para qualquer tamanho se os elementos estão ordenados (e vice versa) 7. Entre os algoritmos de custo quadrático, a inserção é melhor para entradas aleatórias. Para encerrar um quadro comparativo da complexidade dos métodos

Page 17: TRABALHO Def Ord Est Dados Marcos Pacheco

Referências Ophir Frieder, Gideon Frieder, and David Grossman Computer Science Programming

Basics with Ruby O’Reilly Media, 2 Inc 2013

http://eigenclass.blogspot.com.br/2008/10/sorting-algs-in-ruby.html

http://elm200.blogspot.com.br/2011/08/sort-algorithms-in-ruby_09.html http://gillesleblanc.wordpress.com/2012/04/10/sorting-algorithms-in-ruby/ http://jlarusso.github.io/blog/2013/04/30/sorting-algorithms-in-ruby/

http://pt.wikipedia.org/wiki/Heapsort http://homepages.dcc.ufmg.br/~cunha/teaching/20121/aeds2/sortingcmp.pdf http://www.decom.ufop.br/menotti/aedI082/tps/tp3-sol1.pdf