Baixe o app para aproveitar ainda mais
Prévia do material em texto
Quicksort classe Algoritmo de ordenação estrutura de dados Array, Listas ligadas complexidade pior caso complexidade caso médio complexidade melhor caso complexidade de espaços pior caso otimo Não estabilidade não-estável Algoritmos Quicksort Origem: Wikipédia, a enciclopédia livre. (Redirecionado de Quick sort) O algoritmo Quicksort é um método de ordenação muito rápido e eficiente, inventado por C.A.R. Hoare em 1960 , quando visitou a Universidade de Moscovo como estudante. Naquela época, Hoare trabalhou em um projeto de tradução de máquina para o National Physical Laboratory. Ele criou o 'Quicksort ao tentar traduzir um dicionário de inglês para russo, ordenando as palavras, tendo como objetivo reduzir o problema original em subproblemas que possam ser resolvidos mais facil e rapidamente. Foi publicado em 1962 após uma série de refinamentos. O Quicksort é um algoritmo de ordenação por comparação não-estável. Índice 1 O algoritmo 2 Complexidade 3 Implementações 3.1 Pseudocódigo 3.2 Pascal 3.3 PHP 5 - OO 3.4 Delphi (Método Recursivo) 3.5 Visual Basic 3.6 Javascript 3.7 Python 3.8 Assembly x86-gas-Linux 3.9 Haskell 3.10 Erlang 3.11 Lisp 3.12 Perl 3.13 Ruby 3.14 Groovy 3.15 ML 3.16 PHP 3.17 PHP (utilizando pivot) 3.18 C++ 3.19 ASP 3.20 C 3.21 JAVA [1] [2] Algumas etapas do algoritmo Quicksort. 3.22 C# 3.23 Assembly x86 3.24 Prolog 3.25 Lua 4 Comparação com outros algoritmos de ordenação 5 Veja também 6 Referências 7 Ligações externas O algoritmo O Quicksort adota a estratégia de divisão e conquista. A estratégia consiste em rearranjar as chaves de modo que as chaves "menores" precedam as chaves "maiores". Em seguida o Quicksort ordena as duas sublistas de chaves menores e maiores recursivamente até que a lista completa se encontre ordenada. Os passos são: 1. Escolha um elemento da lista, denominado pivô; 2. Rearranje a lista de forma que todos os elementos anteriores ao pivô sejam menores que ele, e todos os elementos posteriores ao pivô sejam maiores que ele. Ao fim do processo o pivô estará em sua posição final e haverá duas sublistas não ordenadas. Essa operação é denominada partição; 3. Recursivamente ordene a sublista dos elementos menores e a sublista dos elementos maiores; A base da recursão são as listas de tamanho zero ou um, que estão sempre ordenadas. O processo é finito, pois a cada iteração pelo menos um elemento é posto em sua posição final e não será mais manipulado na iteração seguinte. Complexidade Complexidade de tempo: θ(n lg n) no melhor caso e caso médio e θ(n ) no pior caso; Complexidade de espaço: θ(lg n) no melhor caso e no caso médio e θ(lg n) no pior caso. R. Sedgewick desenvolveu uma versão do Quicksort com partição recursão de cauda que tem complexidade θ(n ) no pior caso. Implementações Pseudocódigo [3] 2 2 2 2 2 procedimento QuickSort(X[], IniVet, FimVet) var i, j, pivo, aux início i <- IniVet j <- FimVet pivo <- X[(IniVet + FimVet) div 2] enquanto(i < j) | enquanto (X[i] < pivo) faça | | i <- i + 1 | fimEnquanto | enquanto (X[j] > pivo) faça | | j <- j - 1 | fimEnquanto | se (i <= j) então | | aux <- X[i] | | X[i] <- X[j] | | X[j] <- aux | | i <- i + 1 | | j <- j - 1 | fimSe fimEnquanto se (j > IniVet) então | QuickSort(X, IniVet, j) fimSe se (i < FimVet) então | QuickSort(X, i, FimVet) fimse fimprocedimento Pascal program quicksort; uses crt; const left=1; right=10; type vetor = array [left..right]of integer; procedure ordena(var vet:vetor; left:integer; right:integer); var i,j,aux,meio:integer; begin i:=left; j:=right; meio:=vet[(left + right) div 2]; while(i < j)do begin while(vet[i] < meio)do begin i:=i + 1; end; while(vet[j] > meio)do begin j:=j - 1; end; if(i <= j)then begin aux:= vet[i]; vet[i]:=vet[j]; vet[j]:=aux; i:=i + 1; j:=j - 1; end; end; if(j > left)then begin ordena(vet, left, j); end; if(i < right)then begin ordena(vet, i, right); end; end; var vet:vetor; i:integer; begin vet[1]:=2;vet[2]:=4;vet[3]:=7;vet[4]:=5;vet[5]:=8;vet[6]:=10;vet[7]:=3;vet[8]:=1;vet[9]:=6;vet[10]:=9; for i:= 1 to 10 do begin write(vet[i],' '); end; writeln(); writeln(); ordena(vet, left, right); for i:= 1 to 10 do begin write(vet[i],' '); end; readkey; end. PHP 5 - OO class QuickSortUtil { private static function partition(&$array, $f, $l, $property) { $pivot = $array[$f]->$property; while ($f < $l) { while ($array[$f]->$property < $pivot) $l++; while ($array[$l]->$property > $pivot) $f--; $temp = $array[$f]; $array[$f] = $array[$l]; $array[$l] = $temp; } return $f; } public static function sort(&$array, $property, $f=null, $l=null) { if(is_null($f)) $f = 0; if(is_null($l)) $l = count($array)-1; if ($f >= $l) return; $pivot_index = self::partition($array, $f, $l, $property); self::sort($array, $property, $f, $pivot_index); self::sort($array, $property, $pivot_index+1, $l); } } Delphi (Método Recursivo) procedure QuickSort(var A: array of Integer); procedure QuickSort(var A: array of Integer; iLo, iHi: Integer); var Lo, Hi, Mid, T: Integer; begin Lo := iLo; Hi := iHi; Mid := A[(Lo + Hi) div 2]; repeat while A[Lo] < Mid do Inc(Lo); while A[Hi] > Mid do Dec(Hi); if Lo <= Hi then begin T := A[Lo]; A[Lo] := A[Hi]; A[Hi] := T; Inc(Lo); Dec(Hi); end; until Lo > Hi; if Hi > iLo then QuickSort(A, iLo, Hi); if Lo < iHi then QuickSort(A, Lo, iHi); end; begin QuickSort(A, Low(A), High(A)); end; {Chamando em um evento de onClick} procedure TForm1.Button1Click(Sender: TObject); var arr: array[0..100] of integer; I: Integer; begin for I:=Low(arr) to High(arr) do arr[I]:=Random(High(Integer)); Quick_Sort(arr); end; Visual Basic Sub QuickSort(ByRef vetor() As Long, ByVal inicio As Long, ByVal final As Long, ByRef iteracoes Dim pivo As Long Dim i As Long Dim j As Long iteracoes = iteracoes + 1 If final > inicio Then i = inicio j = final pivo = vetor(Fix((inicio + final) / 2)) While i <= j While vetor(i) < pivo i = i + 1 Wend While pivo < vetor(j) j = j - 1 Wend If i <= j Then Call Troca(vetor(i), vetor(j)) i = i + 1 j = j - 1 End If Wend Call QuickSort(vetor, inicio, j, iteracoes) Call QuickSort(vetor, i, final, iteracoes) End If End Sub Sub Troca(ByRef val1 As Long, ByRef val2 As Long) Dim aux As Long aux = val1 val1 = val2 val2 = aux End Sub Javascript function quickSort(vet, esq, dir){ var ce = esq; var cd = dir; var meio = parseInt((ce + cd)/ 2); while(ce < cd){ while(vet[ce] < vet[meio]){ ce++; } while(vet[cd] > vet[meio]){ cd--; }if(ce <= cd){ var temp = vet[ce]; vet[ce] = vet[cd]; vet[cd] = temp; ce++; cd--; } } if(cd > esq) quickSort(vet, esq, cd); if(ce < dir) quickSort(vet, ce, dir); } var vet = [4,10,3,9,7,1,12]; //adicionando elementos document.write(vet.join(" ")+"<br/>"); var esq = 0; var dir = vet.length - 1; //indice máximo do array quickSort(vet, esq, dir); document.write(vet.join(" ")); Python Versão simples def quicksort(v): if len(v) <= 1: return v # uma lista vazia ou com 1 elemento ja esta ordenada less, equal, greater = [], [], [] # cria as sublistas dos maiores, menores e iguais ao pivo pivot = v[0] # escolhe o pivo. neste caso, o primeiro elemento da lista for x in v: # adiciona o elemento x a lista corespondeste if x < pivot: less.append(x) elif x == pivot: equal.append(x) else: greater.append(x) return quicksort(less) + equal + quicksort(greater) # concatena e retorna recursivamente # .. as listas ordenadas Versão in-place def partition(v, left, right): i = left for j in range(left + 1, right + 1): if v[j] < v[left]: # Se um elemento j for menor que o pivo i += 1 # .. incrementa-se i v[i], v[j] = v[j], v[i] # .. e troca o elemento j de posicao o elemento i v[i], v[left] = v[left], v[i] # O pivo e' colocado em sua posicao final return i def quicksort(v, left, right): if right > left: # Verifica se a lista tem 2 ou mais itens pivotIndex = partition(v, left, right) # Pega a posicao do pivo quicksort(v, left, pivotIndex - 1) # Ordena recursivamente os itens menores que o pivo quicksort(v, pivotIndex + 1, right) # Ordena recursivamente os itens maiores que o pivo ''' Exemplo de uso >>> a = [4, 2, 4, 6, 3, 2, 5, 1, 3] >>> quicksort(a, 0, len(a)-1) >>> print a >>> [1, 2, 2, 3, 3, 4, 4, 5, 6] ''' Assembly x86-gas-Linux /*void quicksort_as (int *x, int n);*/ .globl quicksort_as quicksort_as: pushl %ebp movl %esp, %ebp /* 8(%ebp)= ponteiro do arranjo */ /* 12(%ebp)= num de elementos */ movl 12(%ebp), %eax dec %eax movl $4, %ebx mul %ebx pushl %eax pushl $0 pushl 8(%ebp) call quicksort_as_ leave ret quicksort_as_: pushl %ebp movl %esp, %ebp /* 8(%ebp)= ponteiro do arranjo */ /* 12(%ebp)= esq */ /* 16(%ebp)= dir */ movl 12(%ebp), %ecx movl %ecx, %edx movl 8(%ebp), %eax movl 8(%ebp), %eax addl %ecx, %eax movl 16(%ebp), %ecx movl 8(%ebp), %ebx addl %ecx, %ebx /* agora %eax aponta p/ x[esq] e %ebx x[dir]*/ addl %edx, %ecx /*%ecx eh esq + dir*/ pushl %eax movl %ecx, %eax movl $2, %ecx cltd idivl %ecx /* div %eax por 2=%ecx*/ movl $4, %ecx cltd idivl %ecx mul %ecx movl 8(%ebp), %ecx addl %eax, %ecx movl (%ecx), %ecx popl %eax /*%ecx = compare(cmp)*/ quicksort_imj: cmp %eax, %ebx jle quicksort_fim quicksort_inci: cmp (%eax), %ecx jle quicksort_incj addl $4, %eax jmp quicksort_inci quicksort_incj: cmp (%ebx), %ecx jge quicksort_troca subl $4, %ebx jmp quicksort_incj quicksort_troca: cmp %eax, %ebx jl quicksort_fim movl (%ebx), %edx pushl (%eax) movl %edx, (%eax) popl (%ebx) addl $4, %eax subl $4, %ebx jmp quicksort_imj quicksort_fim: /*salvando registradores na pilha p/ fazer chamada de função*/ pushl %eax pushl %ebx /*passando parametros p/ chamada recursiva*/ subl 8(%ebp), %eax cmp %eax, 16(%ebp) jle quicksort_2a_rec pushl 16(%ebp) pushl %eax pushl 8(%ebp) call quicksort_as_ addl $12, %esp quicksort_2a_rec: /*recuperando registradores apos chamada de funcao*/ popl %ebx popl %eax subl 8(%ebp), %ebx cmp %ebx, 12(%ebp) jge quicksort_final /*passando parametros p/ chamada recursiva*/ pushl %ebx pushl 12(%ebp) pushl 8(%ebp) call quicksort_as_ quicksort_final: leave ret Haskell sort :: (Ord a) => [a] -> [a] sort [] = [] sort (pivot:rest) = (sort [y | y <- rest, y < pivot]) ++ [pivot] ++ (sort [y | y <- rest, y >=pivot]) Erlang Uma versão similar a Haskell, utilizando list comprehensions: quicksort([]) -> []; quicksort([Pivot|Rest]) -> quicksort([Smaller || Smaller <- Rest, Smaller =< Pivot]) ++ [Pivot] ++ quicksort([Larger || Larger <- Rest, Larger > Pivot]). Uma versão com melhor performance utilizando tail recursive: qsort([]) -> []; qsort(L=[_|_]) -> qsort(L, []). qsort([], Acc) -> Acc; qsort([Pivot|Rest], Acc) -> partition(Pivot, Rest, {[], [Pivot], []}, Acc). partition(_, [], {Smaller, Equal, Larger}, Acc) -> qsort(Smaller, Equal ++ qsort(Larger, Acc)); partition(Pivot, [H|T], {Smaller, Equal, Larger}, Acc) -> if H < Pivot -> partition(Pivot, T, {[H|Smaller], Equal, Larger}, Acc); H > Pivot -> partition(Pivot, T, {Smaller, Equal, [H|Larger]}, Acc); H == Pivot -> partition(Pivot, T, {Smaller, [H|Equal], Larger}, Acc) end. Lisp (defun partition (fun array) (list (remove-if-not fun array) (remove-if fun array))) (defun sort (array) (if (null array) nil (let ((part (partition (lambda (x) (< x (car array))) (cdr array)))) (append (sort (car part)) (cons (car array) (sort (cadr part))))))) Perl Versões anteriores ao Perl 5.6 utilizavam o algoritmo quicksort para implementar a função sort (http://perldoc.perl.org/functions/sort.html) , então o código em Perl pode resumir-se a: my @ordenada = sort @lista; Como a implementação do quicksort pode assumir tempos quadráticos para algumas entradas, o algoritmo foi substituído na versão 5.8 pelo mais estável mergesort, cujo pior caso é θ(n lg n). Ainda assim, é possível forçar o uso do quicksort através do pragma 'sort' (http://perldoc.perl.org/sort.html) : [4] 2 use sort '_quicksort'; my @ordenada = sort @lista; Uma implementação em Perl puro (mais lenta que o 'sort' embutido) pode ser: sub quicksort { my @lista = @_; my (@menores, @iguais, @maiores); return @lista if @lista < 2; foreach (@lista) { if ($_ < $lista[0]) { push @menores, $_; } elsif ($_ == $lista[0]) { push @iguais, $_; } else { push @maiores, $_; } } return quicksort(@menores), @iguais, quicksort(@maiores); } Já uma versão menor (e certamente menos legível) poderia ser: sub quicksort { return @_ if @_ < 2; my (@iguais, @maiores, @menores); push @{ (\@iguais, \@menores, \@maiores)[ $_[0] <=> $_ ]}, $_ for @_; quicksort(@menores), @iguais, quicksort(@maiores); } Ruby def sort(array) return array if array.size <= 1 pivot = array[0] return sort(array.select { |y| y < pivot }) + array.select { |y| y == pivot } + sort(array.select { |y| y > pivot }) end Groovy def sort(list) { if (list.isEmpty()) return list anItem = list[0] def smallerItems = list.findAll{it < anItem} def equalItems = list.findAll{it = anItem} def largerItems = list.findAll{it > anItem} sort(smallerItems) + equalItems + sort(largerItems) } ML fun filter nil elem cmp = nil | filter (x::xl) elem cmp = if (cmp(x, elem)) then x:: filter xl elem cmp else filter xl elem cmp; fun quicksort nil = nil | quicksort (pivot::xl) = let val small = filter xl pivot (op <); val medium = pivot :: filter xl pivot (op =); val large = filter xl pivot (op >); in (quicksort small) @ medium @ (quicksort large) end; PHP <?php /********************************************************************* *Obs.: a implementação usa parâmetros por referência, isto é, o vetor *passado será modificado. *********************************************************************/ function quicksort(&$vet, $ini, $fim) { $i = $ini; $j = $fim; $dir = 1; while ($i < $j) { if ($vet[$i] > $vet[$j]) { $aux = $vet[$i]; $vet[$i] = $vet[$j]; $vet[$j] = $aux; $dir = - $dir; } if ($dir == 1) $j--; else $i++; } $k = $i; if($ini < $f) quicksort($vet, $ini, $k-1); if($i < $fim) quicksort($vet, $k+1, $fim); } quicksort($vet,0,count($vet)); ?> PHP (utilizando pivot) <?php /* Função utilizando pivot */ function quicksort(&$vet,$ini,$fim) { $i = $ini; $f = $fim; $pivo = $vet[(int)(($ini+$fim)/2)]; while($i < $f) { while($vet[$i] < $pivo) $i++; while($vet[$f] > $pivo) $f--; if($i <= $f) { $aux = $vet[$i]; $vet[$i] = $vet[$f]; $vet[$f] = $aux; $i++; $f--; } } if($ini < $f) quicksort($vet,$ini,$f); if($i < $fim) quicksort($vet,$i,$fim); } ?> C++ #include <algorithm> #include <iterator> #include <functional> using namespace std; template <typename T> void sort(T begin, T end) { if (begin != end) { T middle = partition (begin, end, bind2nd(less<iterator_traits<T>::value_type>(), *begin sort (begin, middle); sort (max(begin + 1, middle), end); } } ASP <% Response.Write("QuickSort Algorithm")& vbNewLine Sub QuickSort(vec,loBound,hiBound) Dim pivot,loSwap,hiSwap,temp '== Two items to sort if hiBound - loBound = 1 then if vec(loBound) > vec(hiBound) then temp=vec(loBound) vec(loBound) = vec(hiBound) vec(hiBound) = temp End If End If '== Three or more items to sort pivot = vec(int((loBound + hiBound) / 2)) vec(int((loBound + hiBound) / 2)) = vec(loBound) vec(loBound) = pivot loSwap = loBound + 1 hiSwap = hiBound do '== Find the right loSwap while loSwap < hiSwap and vec(loSwap) <= pivot loSwap = loSwap + 1 wend '== Find the right hiSwap while vec(hiSwap) > pivot hiSwap = hiSwap - 1 wend '== Swap values if loSwap is less then hiSwap if loSwap < hiSwap then temp = vec(loSwap) vec(loSwap) = vec(hiSwap) vec(hiSwap) = temp End If loop while loSwap < hiSwap vec(loBound) = vec(hiSwap) vec(hiSwap) = pivot '== Recursively call function .. the beauty of Quicksort '== 2 or more items in first section if loBound < (hiSwap - 1) then Call QuickSort(vec,loBound,hiSwap-1) '== 2 or more items in second section if hiSwap + 1 < hibound then Call QuickSort(vec,hiSwap+1,hiBound) End Sub 'QuickSort Sub PrintArray(vec,lo,hi) '== Simply print out an array from the lo bound to the hi bound. Dim i For i = lo to hi Response.Write vec(i) Next End Sub 'PrintArray Randomize Dim x(9) For z = 0 to 9 x(z) = int(Rnd*1000) If (Rnd < 0.5) then x(z) = x(z)-1000 Next Response.Write ("Here is a jumbled array:") & vbNewLine Call PrintArray(x,0,9) Call QuickSort(x,0,9) Response.Write("Now the array is sorted!")& vbNewLine Call PrintArray(x,0,9) Response.Write(vbNewLine) %> C void swap(int* a, int* b) { int tmp; tmp = *a; *a = *b; *b = tmp; } int partition(int vec[], int left, int right) { int i, j; i = left; for (j = left + 1; j <= right; ++j) { if (vec[j] < vec[left]) { ++i; swap(&vec[i], &vec[j]); } } swap(&vec[left], &vec[i]); return i; } void quickSort(int vec[], int left, int right) { int r; if (right > left) { r = partition(vec, left, right); quickSort(vec, left, r - 1); quickSort(vec, r + 1, right); } } Implementação quicksort testado com ate 1000000 de elementos para dados crescente, decrescente e aleatório void swap(int *a, int i, int j) { int t = a[i]; a[i] = a[j]; a[j] = t; } int partition(int *a, int left,int right,int pivot) { int pos, i; swap(a, pivot, right); pos = left; for(i = left; i < right; i++) { if (a[i] < a[right]) { swap(a, i, pos); pos++; } } swap(a, right, pos); return pos; } void quick(int *a, int left, int right) { if (left < right) { int pivot = (left+right)/2; int pos = partition(a,left,right,pivot); quick(a,left,pos-1); quick(a,pos+1,right); } } Implementaçao usando 'fat pivot': void sort(int array[], int begin, int end) { int pivot = array[begin]; int i = begin + 1, j = end, k = end; int t; while (i < j) { if (array[i] < pivot) i++; else if (array[i] > pivot) { j--; k--; t = array[i]; array[i] = array[j]; array[j] = array[k]; array[k] = t; } else { j--; swap(array[i], array[j]); } } i--; swap(array[begin], array[i]); if (i - begin > 1) sort(array, begin, i); if (end - k > 1) sort(array, k, end); } Lembrando que quando você for chamar a função recursiva terá que chamar a mesma da seguinte forma ordenar_quicksort_nome(0,n-1). O 0(zero) serve para o início receber a posição zero do vetor e o fim será o tamanho do vetor -1. void ordenar_quicksort_nome(int ini, int fim) { int i = ini, f = fim; char pivo[50]; strcpy(pivo,vetor[(ini+fim)/2]); if (i<=f) { while (strcmpi(vetor[i],pivo)<0) i++; while (strcmpi(vetor[f],pivo)>0) f--; if (i<=f) { strcpy (aux_char,vetor[i]); strcpy (vetor[i],vetor[f]); strcpy (vetor[f],aux_char); i++; f--; } } if (f>ini) ordenar_quicksort_nome(ini,f); if (i<fim) ordenar_quicksort_nome(i,fim); } JAVA public static void quick_sort(int []v,int ini, int fim) { int meio; if (ini < fim) { meio = partition(v, ini, fim); quick_sort(v, ini, meio); quick_sort(v, meio + 1, fim); } } public static int partition(int []v, int ini, int fim) { int pivo, topo, i; pivo = v[ini]; topo = ini; for (i = ini + 1; i <= fim; i++) { if (v[i] < pivo) { v[topo] = v[i]; v[i] = v[topo + 1]; topo++; } } v[topo] = pivo; return topo; } C# static class QuickSort { public static void Ordenar(int[] vetor) { Ordenar(vetor, 0, vetor.Length - 1); } private static void Ordenar(int[] vetor, int inicio, int fim) { if (inicio < fim) { int posicaoPivo = Separar(vetor, inicio, fim); Ordenar(vetor, inicio, posicaoPivo - 1); Ordenar(vetor, posicaoPivo + 1, fim); } } private static int Separar(int[] vetor, int inicio, int fim) { int pivo = vetor[inicio];int i = inicio + 1, f = fim; while (i <= f) { if (vetor[i] <= pivo) i++; else if (pivo < vetor[f]) f--; else { int troca = vetor[i]; vetor[i] = vetor[f]; vetor[f] = troca; i++; f--; } } vetor[inicio] = vetor[f]; vetor[f] = pivo; return f; } } Assembly x86 qsort: @ Takes three parameters: @ a: Pointer to base of array a to be sorted (arrives in r0) @ left: First of the range of indexes to sort (arrives in r1) @ right: One past last of range of indexes to sort (arrives in r2) @ This function destroys: r1, r2, r3, r4, r5, r7 stmfd sp!, {r4, r6, lr} @ Save r4 and r6 for caller mov r6, r2 @ r6 <- right qsort_tailcall_entry: sub r7, r6, r1 @ If right - left <= 1 (already sorted), cmp r7, #1 ldmlefd sp!, {r1, r6, pc} @ Return, moving r4->r1, restoring r6 ldr r7, [r0, r1, asl #2] @ r7 <- a[left], gets pivot element add r2, r1, #1 @ l <- left + 1 mov r4, r6 @ r <- right partition_loop: ldr r3, [r0, r2, asl #2] @ r3 <- a[l] cmp r3, r7 @ If a[l] <= pivot_element, addle r2, r2, #1 @ ... increment l, and ble partition_test @ ... continue to next iteration. sub r4, r4, #1 @ Otherwise, decrement r, ldr r5, [r0, r4, asl #2] @ ... and swap a[l] and a[r]. str r5, [r0, r2, asl #2] str r3, [r0, r4, asl #2] partition_test: cmp r2, r4 @ If l < r, blt partition_loop @ ... continue iterating. partition_finish: sub r2, r2, #1 @ Decrement l ldr r3, [r0, r2, asl #2] @ Swap a[l] and pivot str r3, [r0, r1, asl #2] str r7, [r0, r2, asl #2] bl qsort @ Call self recursively on left part, @ with args a (r0), left (r1), r (r2), @ also preserves r6 and @ moves r4 (l) to 2nd arg register (r1) b qsort_tailcall_entry @ Tail-call self on right part, @ with args a (r0), l (r1), right (r6) Prolog partition([], _, [], []). partition([X|Xs], Pivot, Smalls, Bigs) :- ( X @< Pivot -> Smalls = [X|Rest], partition(Xs, Pivot, Rest, Bigs) ; Bigs = [X|Rest], partition(Xs, Pivot, Smalls, Rest) ). quicksort([]) --> []. quicksort([X|Xs]) --> { partition(Xs, X, Smaller, Bigger) }, quicksort(Smaller), [X], quicksort(Bigger). Lua function quickSort(v, ini, fim) i, j = ini, fim pivo = v[math.floor((ini + fim)/2)] while i <= j do while (v[i] < pivo) do i=i+1 end while (v[j] > pivo) do j=j-1 end if (i<=j) then v[i], v[j] = v[j], v[i] i, j = i+1, j-1 end end if j > ini then quickSort(v, ini, j) end if i < fim then quickSort(v, i, fim) end end Comparação com outros algoritmos de ordenação Quicksort é uma versão optimizada de uma árvore binária ordenada. Em vez de introduzir itens sequencialmente numa árvore explicita, o Quicksort organiza-os correntemente na árvore onde está implícito, fazendo-o com chamadas recursivas à mesma. O algoritmo faz exactamente as mesmas comparações, mas com uma ordem diferente. O algoritmo que mais se familiariza com o Quicksort é o Heapsort. Para o pior caso neste algoritmo temos . Mas, o Heapsort em média trata-se de uma algoritmo mais lento que o Quicksort, embora tenha sido muito debatido essa afirmação. No Quicksort permanece o caso do pior caso, à excepção quando se trata de usar a variante Intro sort, que muda para Heapsort quando um pior caso é detectado. Caso se saiba à partida que será necessário o uso do heapsort é aconselhável usá-lo directamente, do que usar o introsort e depois chamar o heapsort, torna mais rápido o algoritmo. O Quicksort também compete com o Mergesort, outro algoritmo de ordenação recursiva, tendo este o benefício de ter como pior caso . Mergesort, ao contrário do Quicksort e do Heapsort, é estável e pode facilmente ser adptado para operar em listas encadeadas e em listas bastantes grandes alojadas num tipo de acesso lento a média como um Network-Attached Storage ou num disco. Embora o Quicksort possa ser operado em listas encadeadas, por vezes escolhendo um mau pivô sem acesso aleatório. A maior desvantagem do Mergesort é que quando opera em arrays, requer de espaço para o melhor caso, considerando que o Quicksort com um particionamento espacial e com recursão utiliza apenas de espaço. Bucket sort com dois buckets é muito parecido ao Quicksort (quase idêntico), o pivô neste caso é garantidamente o valor do meio do vector. Veja também Ordenação de vetor Merge sort Heapsort Selection sort Bubble sort Busca linear Referências 1. ↑ AZEREDO, Paulo A.. Métodos de Classificação de Dados e Análise de suas Complexidades. Rio de Janeiro: Campus, 1996. ISBN 85-352-0004-5 2. ↑ An Interview with C.A.R. Hoare (http://cacm.acm.org/magazines/2009/3/21782-an-interview-with-car- hoare/fulltext) . Communications of the ACM, March 2009 ("premium content"). 3. ↑ BAASE, Sara. Computer Algorithms: Introduction to Design and Analysis (em inglês). 2ª ed. Reading, Massachusetts: Addison-Wesley, 1988. 53 p. ISBN 0-201-06035-3 4. ↑ Documentação oficial da função 'sort' em Perl (http://perldoc.perl.org/functions/sort.html) . perl.org. Página visitada em 2008-10-20. Ligações externas Rápida aula de Quicksort (http://www.ime.usp.br/~pf/algoritmos/aulas/quick.html) Animação do processo de ordenação pelo Quicksort (http://www.cs.ubc.ca/spider/harrison/Java/sorting- demo.html) Explanação video de Quicksort usando cartões e de código em C++ (http://www.datastructures.info/what-is-quicksort-and-how-does-it-work-quick-sort-algorithm/) QuickSort Code (http://www.algorithm-code.com/wiki/Quick_Sort) Obtida de "http://pt.wikipedia.org/w/index.php?title=Quicksort&oldid=33213416" Categoria: Algoritmos de ordenação Navigation menu Esta página foi modificada pela última vez à(s) 15h17min de 7 de dezembro de 2012. Este texto é disponibilizado nos termos da licença Atribuição-Partilha nos Mesmos Termos 3.0 não Adaptada (CC BY-SA 3.0); pode estar sujeito a condições adicionais. Consulte as condições de uso para mais detalhes.
Compartilhar