Programação II. Tópicos Extras Ordenação (sort) Bruno Feijó Dept. de Informática, PUC-Rio

Documentos relacionados
Programação II. Ordenação (sort) Bruno Feijó Dept. de Informática, PUC-Rio

Programação II. Ordenação (sort) Bruno Feijó Dept. de Informática, PUC-Rio

Programação II. Ordenação (sort) Bruno Feijó Dept. de Informática, PUC-Rio

Programação II. Busca em Vetor (search) Bruno Feijó Dept. de Informática, PUC-Rio

INF 1007 Programação II

Módulo 16 - Ordenação

Programação de Computadores II. Cap. 16 Ordenação

Módulo 16 - Ordenação. Referências

Linguagem C: Ordenação

Programação II. Árvores Binárias (Binary Trees) Bruno Feijó Dept. de Informática, PUC-Rio

INF1007: Programação 2 6 Ordenação de Vetores. 01/10/2015 (c) Dept. Informática - PUC-Rio 1

Estruturas de Dados. Módulo 17 - Busca. 2/6/2005 (c) Dept. Informática - PUC-Rio 1

INF 1010 Estruturas de Dados Avançadas

Análise de Algoritmos Estrutura de Dados II

INF 1007 Programação II

ponteiros INF Programação I Prof. Roberto Azevedo

Programação II. Ordenação (sort) Bruno Feijó Dept. de Informática, PUC-Rio

Recuperação P1 de Estrutura de Dados

CES-11. Noções de complexidade de algoritmos. Complexidade de algoritmos. Avaliação do tempo de execução. Razão de crescimento desse tempo.

Programação II. Vetores Bidimensionais e Vetores de Ponteiros. Bruno Feijó Dept. de Informática, PUC-Rio

Programação II. Vetor de Tipo Estruturado e Vetor de Ponteiros. Bruno Feijó Dept. de Informática, PUC-Rio

Introdução à Programação

Introdução à Ciência da Computação II

Aula 18 Algoritmos básicos de busca e classificação

CT-234. Estruturas de Dados, Análise de Algoritmos e Complexidade Estrutural. Carlos Alberto Alonso Sanches

Estrutura de Dados. Algoritmos de Ordenação. Prof. Othon M. N. Batista Mestre em Informática

Permite modularidade (dividir programa em partes): Facilita a depuração (debug) e portabilidade.

Prova 1 PMR3201 Computação para Automação 1o. semestre 2016 Prof. Thiago de Castro Martins

Programação II. Tipos Estruturados

Programação II. Vetores e Alocação Dinâmica. Bruno Feijó Dept. de Informática, PUC-Rio

Os métodos de ordenação que ordenam os elementos in situ podem ser classificados em três principais categorias:

7. Introdução à Complexidade de Algoritmos

Complexidade de algoritmos Notação Big-O

INF 1010 Estruturas de Dados Avançadas

Universidade Federal de Santa Maria Colégio Agrícola de Frederico Westphalen Curso Superior de Tecnologia em Sistemas para Internet

BCC202 - Estrutura de Dados I

INTRODUÇÃO À LINGUAGEM C

CURSO DE ESTRUTURA DE DADOS MÓDULO: ALGORITMOS DE ORDENAÇÃO E PESQUISA PROFESSORA: DANIELA ELOISE FLÔR COLABORADORA: MARIA CAROLINA SILA VANUCHI

CIC 110 Análise e Projeto de Algoritmos I

AED2 - Aula 11 Problema da separação e quicksort

INF 1620 P1-13/09/02 Questão 1 Nome:

Programação II. Vetores e Alocação Dinâmica. Bruno Feijó Dept. de Informática, PUC-Rio

1. Faça um programa que leia uma string digitada pelo usuário e salve em um arquivo em branco.

Estruturas de Dados. Introdução Definição de Ponteiros Declaração de Ponteiros em C Manipulação de Ponteiros em C

UNIVERSIDADE FEDERAL DO ESPÍRITO SANTO CENTRO UNIVERSITÁRIO NORTE DO ESPÍRITO SANTO

ALGORITMOS E ESTRUTURAS DE DADOS CES-11 Prof. Paulo André Castro Sala 110 Prédio da Computação IECE - ITA

ALGORITMOS DE ORDENAÇÃO

SCC Capítulo 2 Recursão

INTRODUÇÃO À LINGUAGEM C

Teoria da Computação Aula 9 Noções de Complexidade

Tipos Básicos. Operadores de Incremento e Decremento. Operador Sizeof. Estruturas de Dados Aula 2: Estruturas Estáticas

Projeto e Análise de Algoritmos

Comportamento assintótico

Estruturas de Dados Aula 2: Estruturas Estáticas. Tipos Básicos. Quantos valores distintos podemos representar com o tipo char?

Estruturas de Dados Aula 2: Estruturas Estáticas 02/03/2011

Programação II. Listas Encadeadas (Linked Lists) Bruno Feijó Dept. de Informática, PUC-Rio

Algoritmos e Estruturas de Dados LEE 2013/2014. popular devido à facilidade de implementação e eficiência

Marcelo Keese Albertini Faculdade de Computação Universidade Federal de Uberlândia

1. O que é a eficiência assintótica de um algoritmo. Explique com suas palavras.

DAS5102 Fundamentos da Estrutura da Informação

ESTRUTURAS DE DADOS E ALGORITMOS APRESENTAÇÃO DO CURSO E INTRODUÇÃO

REVISÃO DE C. Vanessa Braganholo Estruturas de Dados e Seus Algoritmos

1 Exercícios com ponteiros

AED - Algoritmos e Estruturas de Dados Licenciatura em Engenharia Electrónica

5. Algoritmos de Ordenação

INTRODUÇÃO À LINGUAGEM C

Projeto e Análise de Algoritmos

1ª Lista de Exercícios

Centro Federal de Educação Tecnológica de Minas Gerais Programa de Pós-Graduação em Modelagem Matemática e Computacional

Variáveis indexadas. Capítulo Vetores numéricos

Carlos Eduardo Batista. Centro de Informática - UFPB

Módulo 5 Vetores e Alocação Dinâmica

Programação de Computadores II. Cap. 17 Busca

Prof. A. G. Silva. 25 de abril de Prof. A. G. Silva INE5231 Computação Científica I 25 de abril de / 68

Quick Sort. Considerações Sobre Algoritmos de Ordenação. Estagiário PAE: Jesimar da S. Arantes Professor: ClaudioQuick F. M.

Programação Estruturada Prof. Rodrigo Hausen Organização e Gerenciamento de Memória

Programação Estruturada Prof. Rodrigo Hausen Ponteiros e Passagem de Parâmetros

5. Análise de Complexidade de Algoritmos. João Pascoal Faria (versão original) Ana Paula Rocha (versão 2003/2004) Luís Paulo Reis (versão 2005/2006)

Algoritmos de Ordenação: QuickSort

Departamento de Engenharia Rural Centro de Ciências Agrárias. Programação I

Programação: Vetores

Programação de Computadores Ordenação de Arranjos

Aula 3 Listas Lineares Sequenciais Ordenadas. prof Leticia Winkler

7. Introdução à Complexidade de Algoritmos

Análise de Complexidade. Algoritmos e Estruturas de Dados Flavio Figueiredo (

3. Linguagem de Programação C

Análise de Complexidade de Algoritmos. mario alexandre gazziro

Universidade Estadual de Mato Grosso do Sul Bacharelado em Ciência da Computação Algoritmos e Estruturas de Dados II Prof. Fabrício Sérgio de Paula

André Vignatti DINF- UFPR

Algoritmos de Ordenação. Profº Carlos Alberto T. Batista

BCC202 - Estrutura de Dados I

Quick Sort. Considerações Sobre Algoritmos de Ordenação. Estagiário PAE: Jesimar da S. Arantes Professor: Claudio Quick F. M.

QuickSort. Algoritmos e Estruturas de Dados Verão Cátia Vaz 1

3. Linguagem de Programação C

Programação de Computadores II. Cap. 5 Vetores

Introdução a Programação. Ponteiros e Vetores, Alocação Dinâmica

1 Exercícios com ponteiros

Algoritmos de Ordenação

Linguagem C: Introdução

Transcrição:

Programação II Tópicos Extras Ordenação (sort) Bruno Feijó Dept. de Informática, PUC-Rio

qsort Quick Sort da Biblioteca C

Ponteiros para Funções Em C é possível definir ponteiros para funções que podem ser colocados em vetores, passados para funções e retornados por funções No exemplo a seguir, a função opera(m, x, y, func) recebe um ponteiro de função como um de seus argumentos (func) e retorna m func(x,y). Devemos notar que o nome da função mult é um ponteiro quando escrevemos opera(2,3,5,mult); #include <stdio.h> Se argumentos são ponteiros, usamos const quando queremos garantir que a função func não modificará os valores que são int mult(int x,int y); apontados: int(*func)(const int *, const int *)) int soma(int x, int y); int opera(int m, int x, int y, int(*func)(int, int)); int main(void) int a, b; a = opera(2,3,5,mult); b = opera(2,3,5,soma); printf("%d %d\n",a,b); return 0; Saída: 30 16 int mult(int x,int y) return x*y; int soma(int x, int y) return x+y; int opera(int m,int x,int y,int(*func)(int, int)) return m*func(x,y);

Quick Sort da stdlib do C void qsort(void * v, int n, int tam, int (*cmp)(const void *, const void *)); v: vetor de ponteiros genéricos n: número de elementos do vetor tam: tamanho em bytes de cada elemento (use sizeof para especificar) cmp: ponteiro para função que compara elementos genéricos int nome(const void * a, const void * b); deve retornar <0 se a<b, >0 se a>b e 0 se a == b const é para garantir que a função não modificará os valores dos elementos static int compfloat(const void * a, const void * b) /* converte os ponteiros genericos */ float * aa = (float *)a; float * bb = (float *)b; /* faz a comparacao com (*aa) e (*bb) retornando -1,0, ou 1 */ if (*aa > *bb) // atenção para o * return 1; else if (*aa < *bb) return -1; else return 0; chamada: qsort(v,n,sizeof(float),compfloat); // N é o tamanho de v

Exemplo Quick Sort da stdlib #include <stdlib.h> int main(void)... void QsortPessoa(int n, Pessoa ** v) qsort(v,n,sizeof(pessoa *),comppessoa); Pessoa tab[] = "Diana Maria",22,...; Pessoa * v[] = tab,tab+1,...;... QsortPessoa(n,tabPessoa); // ordenacao com Quick Sort... int comppessoa(const void * a, const void * b) Pessoa ** aa = (Pessoa **)a; Pessoa ** bb = (Pessoa **)b; int cmp = strcmp((*aa)->nome,(*bb)->nome); if (cmp>0 (cmp==0 && ((*aa)->idade>(*bb)->idade))) return 1; else if (cmp<0 (cmp==0 && ((*aa)->idade<(*bb)->idade))) return -1; else return 0;

Bubble Sort

Bubble Sort Ordem Crescente Apenas de interesse didático e de referência A idéia é ir comparando dois vizinhos e trocando o menor pelo maior até que o maior de todos fica no final (como se o maior fosse uma bolha que sobe até o topo) 0 1 0 1 1 2... 1 2...... j j+1... j j+1 passo 1 passo 2 passo 3... Este é o maior de todos Este é o segundo maior de todos

Exemplo Bubble Sort Passo 1 e Passo 2 n 1 comparações (i.e. 7) n = 8 elementos 25 48 37 12 57 86 33 92 25x48 25 48 37 12 57 86 33 92 48x37 troca 25 37 48 12 57 86 33 92 48x12 troca 25 37 12 48 57 86 33 92 48x57 25 37 12 48 57 86 33 92 57x86 25 37 12 48 57 86 33 92 86x33 troca 25 37 12 48 57 33 86 92 86x92 25 37 12 48 57 33 86 92 final do passo 1 o maior elemento, 92, já está na sua posição final n 2 comparações (i.e. 6) 25 37 12 48 57 33 86 92 25x37 25 37 12 48 57 33 86 92 37x12 troca 25 12 37 48 57 33 86 92 37x48 25 12 37 48 57 33 86 92 48x57 25 12 37 48 57 33 86 92 57x33 troca 25 12 37 48 33 57 86 92 57x86 25 12 37 48 33 57 86 92 final do passo 2 o segundo maior elemento, 86, já está na sua posição final

Bubble Sort Passo 3 e Passo 4 n 3 (= 5) 25 12 37 48 33 57 86 92 25x12 troca 12 25 37 48 33 57 86 92 25x37 12 25 37 48 33 57 86 92 37x48 12 25 37 48 33 57 86 92 48x33 troca 12 25 37 33 48 57 86 92 48x57 12 25 37 33 48 57 86 92 final passo 3 Idem para 57. n 4 (= 4) 12 25 37 33 48 57 86 92 12x25 12 25 37 33 48 57 86 92 25x37 12 25 37 33 48 57 86 92 37x33 troca 12 25 33 37 48 57 86 92 37x48 12 25 33 37 48 57 86 92 final do passo 4 Idem para 48. Não irá trocar mais. Veja isto no próximo passo

Bubble Sort Passos 5, 6 e 7 n 5 (= 3) Passo 5 sem troca! Os dois próximos passos são desperdícios! 12 25 33 37 48 57 86 92 12x25 12 25 33 37 48 57 86 92 25x33 12 25 33 37 48 57 86 92 33x37 12 25 33 37 48 57 86 92 final do passo 5 Idem para 37. n 6 (= 2) 12 25 33 37 48 57 86 92 12x25 12 25 33 37 48 57 86 92 25x33 12 25 33 37 48 57 86 92 final do passo 6 Idem para 33. n 7 (= 1) 12 25 33 37 48 57 86 92 12x25 12 25 33 37 48 57 86 92 final do passo 7 Idem para 25 e, conseqüentemente, 12. 12 25 33 37 48 57 86 92 final da ordenação

Código bolhaint Ordem Crescente bolhaint(vetor v de inteiros, n) i = n-1 para cada i, enquanto i>0 hatroca= 0 j = 0 para cada j, enquanto j<i se compint(v j,v j+1 ) é VERDADE troca v j e v j+1 hatroca= 1; // marca troca incrementa j de 1 if hatroca é zero retorna decrementa i de 1 static int compint(int a, int b) return a > b; void bolhaint(int * v, int n) int i,j,hatroca; int temp; for (i=n-1;i>0;i--) hatroca= 0; for (j=0;j<i;j++) if (compint(v[j],v[j+1])) temp = v[j]; v[j] = v[j+1]; troca v[j+1] = temp; hatroca= 1; if (hatroca==0) return; Para outros tipos, só muda o que está em vermelho e itálico

Código bolhastr Ordem Crescente void bolhastr(char ** v, int n) int i,j,hatroca; char * temp; for (i=n-1;i>0;i--) hatroca= 0; for (j=0;j<i;j++) if (compstr(v[j],v[j+1])) temp = v[j]; v[j] = v[j+1]; troca v[j+1] = temp; hatroca= 1; if (hatroca==0) return; int main(void) char * v[] = "daniel","ana",...,;... bolhastr(tab, N);... static int compstr(char * a, char * b) return (strcmp(a,b) > 0); strcmp(x,y) é uma função da biblioteca de strings que retorna o seguinte: < 0 se o primeiro caractere que não casa tem um valor mais baixo em x do que em y 0 se os conteúdos dos dois strings são iguais >0 se o primeiro caractere que não casa tem um valor mais alto em x do que em y Por ex.: strcmp("daniel","ana") retorna > 0 strcmp("ana","ana") retorna < 0 (porque 'A' é menor que 'a' na tabela ASCII

Algoritmo Genérico void bolhagen(void * v, int n, int tam, int(*comp)(const void *, const void *)) int i,j,hatroca; void * p1; void * p2; for (i=n-1;i>0;i--) hatroca= 0; for (j=0;j<i;j++) p1 = acessa(v,j,tam); p2 = acessa(v,j+1,tam); if (comp(p1,p2)) troca(p1,p2,tam); void ordenapessoa(int n, Pessoa ** v) hatroca= 1; bolhagen(v,n,sizeof(pessoa *),comppessoa); if (hatroca==0) return; Assunto Avançado static void * acessa(void * v,int i,int tam) char * t = (char *)v; // char = 1 byte t += tam*i; return (void *)t; static void troca(void * a, void * b, int tam) char temp; char * v1 = (char *)a; // troca byte a byte char * v2 = (char *)b; int i; for (i=0; i<tam; i++) temp = v1[i]; v1[i] = v2[i]; v2[i] = temp; static int comppessoagen(const void * a, const void * b) Pessoa ** aa = (Pessoa **)a; Pessoa ** bb = (Pessoa **)b; int cmp = strcmp((*aa)->nome,(*bb)->nome); return (cmp>0 (cmp==0 && (*aa)->idade > (*bb)->idade));

Selection Sort (Ordenação por Seleção)

Conceito do Selection Sort Ordem Crescente - Supomos que o maior elemento (max) é o que está na posição 0 - A partir da posição 1, procuramos se há alguém maior (max) do que o valor na posição 0 - trocamos este máximo pelo último - Deslocamos o fim do vetor para 1 (uma) posição à esquerda - Repetimos o processo fim fim fim Note que o processo vai dividindo o vetor em uma parte ordenada e outra não ordenada. fim Um processo equivalente é trabalhar com o mínimo e trocar com o primeiro. Neste caso, o vetor ordenado vai se construindo à esquerda. fim

Selection Sort void selectionint(int * v, int n) int fim, imax, i; int temp; for (fim = n-1; fim > 0; fim--) imax= 0; /* indice do maior*/ for (i=1;i<=fim;i++) if ( v[i]> v[imax] ) imax = i; temp = v[fim]; v[fim] = v[imax]; v[imax] = temp; Implemente a versão que trabalha com o mínimo! troca Ou usando uma função para um critério genérico critério if ( compint(v[i], v[imax]) ) static int compint(int a, int b) return a > b;

Complexidade (assunto avançado)

Eficiência e Complexidade Geralmente avaliamos algoritmos em termos das seguintes métricas: O quão rápido o algoritmo executa (eficiência de tempo) O quanto de memória ele requer (eficiência de espaço) Estas métricas dependem de: 1. Qualidade do código; 2. Natureza do processador; 3. Dados de entrada. Supondo que o algoritmos têm a melhor qualidade de código possível e rodam num mesmo excelente processador, vamos analisar a questão dos dados. Ao invés de calcular exatamente quanto tempo e quanto espaço consome um determinado algoritmo, vamos estimar um valor limite superior. E mais: nos slides a seguir, vamos analisar apenas o tempo.

Complexidade de Tempo O tempo gasto por um algoritmo é função do tamanho n da entrada de dados e depende do número de operações que cada passo do algoritmo executa. T(n) indica a dimensão este tempo de uma forma geral (e independente de hardware) No caso do algoritmo Bubble, numa análise aproximada, o passo 1 faz n-1 comparações, o passo 2 faz n-2 comparações,.... De maneira aproximada, temos: T ( n) = ( n 1) + ( n 2) + + 2 + 1 Isto é igual à soma de uma série aritmética de m termos, onde m = n-1: (n-1) + (n-2) +... + 2 + 1 Série Aritmética S m = m(a 1 + a m )/2 a m a 1 m = n-1 S m = n(n-1)/2 1 1 T ( n) = n( n 1) / 2 = n 2 n 2 2 Para grandes valores de n (n ), esta função é limitada pela função bn 2, onde b é uma constante, chamada de upper bound, i.e.: 1 2 1 2 T ( n) = n n bn 2 2 Como regra geral, o termo de mais alta ordem de uma função domina sua taxa de crescimento (i.e., na prática, suprimimos constantes multiplicativas e termos de baixa ordem para descrever o comportamento limite de uma função) Dizemos, então, que o algoritmo Bubble tem uma complexidade de tempo quadrática e usamos a notação do Big O para indicar este limite superior: O(n 2 )

Complexidades Comuns (notação Big O) Notação Big O O(1) O(log n) O(n) O(n log n) O(n 2 ) Tempo constante Tempo logarítmico Tempo linear Tempo loglinear (ou quaselinear) Tempo quadrático Limite n 2 T ( n) = 1 2 n 2 Quase linear 1 2 n n

Diferença entre n e log n tamanho 10 60 600 3 600 86 400 2 592 000 946 080 000 94 608 000 000 O(n) 10 seg 1 min 10 min 1 h 1 dia 1 mês 1 ano 100 anos O(log n) 3 seg 6 9 12 16 21 30 36 seg

Outras Considerações sobre Complexidade Na análise de complexidade, procuramos o Pior Caso, o Melhor Caso e o Caso Médio Bubble Sort tem o Melhor Caso quando a lista já está ordenada. Neste caso, a complexidade de tempo é O(n). Uma única passada resolve. O Caso Médio para Bublle Sort também é O(n 2 ) Entre algoritmos de mesma complexidade, há diferenças em eficiência Por exemplo, Selection Sort é similar ao Bubble Sort e ambos tem O(n 2 ), isto é: ele faz o mesmo número de comparações que o Bubble. Entretanto, Selection Sort tem um menor número de comparações e tende a ser aproximadamente 2 vezes mais eficiente. Eficiência não é a mesma coisa que complexidade! O Bubble Sort com ou sem o flag de interrupção é O(n 2 ), sendo o com flag mais eficiente. Em geral uma única operação (ou comando) tem um tempo de execução de O(1) Um loop (laço) que é repetido n vezes tem O(n) Dois laços aninhados (nested loops) indo de 1 a n tem O(n 2 ) Se um algoritmo tem vários passos de complexidades diferentes, a complexidade do algoritmo como um todo é dado pelo máximo. Por exemplo, um algoritmo com 3 passos de O(n 2 ), O(n 2 ) e O(n), tem complexidade O(n 2 ) Um algoritmo com 3 linhas de commandos, sem loop, tem 3 passos O(1), O(1) e O(1), o que leva a um algoritmo de complexidade O(1).

Complexidade do Quick Sort Pior Caso A primeira etapa do algortimo de sort é colocar o pivô x na posição que divide o vetor v entre os elementos menores que x e os maiores que x : k n-k x Esta etapa (que caminha pelo vetor, compara e troca valores) consome um tempo cn (*). As outras duas etapas são as chamadas recursivas. Temos, então: T ( n) = T ( k) + T ( n k) + cn PIOR CASO: pivô x é o menor, em cada passo (**). Neste caso, k =1 e n-k = n-1 passo 1: passo 2: passo 3:... T ( n) = T (1) + T ( n 1) + cn TT nn = TT 1 + TT 1 + TT nn 2 + cc nn 1 + cccc = TT nn 2 + 2TT 1 + cc nn 1 + nn T ( n) = [ T (1) + T ( n 3) + c( n 2)] + 2T (1) + c( n 1+ n) = T ( n 3) + 3T (1) + c( n 2 + n 1+ n) passo i: T ( n) = T ( n i) + it (1) + c( n i + 1+ + n 1+ n) A soma da série aritmética de i termos n i+1,...,n 1,n é: S i = i( 2n + 1 i) / 2 e considerando que vamos até n i=1, i.e. i = n 1, temos: T ( n) = nt (1) + c( n 1)( n + 2) 2 2 A complexidade é, portanto: T ( n) = nt (1) + c( n 1)( n + 2) dn O( n ) O mesmo vale para pivô x sendo o maior. (*) o maior valor de c seria para um código que percorresse uma vez o vetor, guardando os elementos menores do que x (e o próprio x) em um vetor temporário, percorresse novamente o vetor, guardando os elementos maiores do que x, e finalmente copiasse o vetor temporário para o vetor original. Neste caso, o tempo seria 4n (i.e. c = 4). (**) Neste caso, sempre haverá apenas um único elemento em um subvetor e todos os outros no outro subvetor. Trata-se de uma situação muito desbalanceada. O mesmo ocorre se o pivô é sempre o maior em cada passo.

Complexidade do Quick Sort Melhor Caso MELHOR CASO: pivô x divide vetor em duas partes iguais, em cada passo. Neste caso, k =n/2 e n-k = n/2 passo 1: passo 2: passo 3:... passo i: T ( n) = T ( n / 2) + T ( n / 2) + cn = 2T ( n / 2) + cn 2 2 T ( n) = 2[2T ( n / 4) + cn / 2] + cn = 2 T ( n / 2 ) + 2cn 2 3 2 3 3 T ( n) = 2 [2T ( n / 2 ) + cn / 2 ] + 2cn = 2 T ( n / 2 ) + 3cn i i T ( n) = 2 T ( n / 2 ) + icn considerando que vamos até n/2 i = 1, i.e. n = 2 i, ou seja, i = log n, temos: T ( n) = nt (1) + cnlog n dnlog n O n ( log n) A mediana é o valor separando a metade mais alta de uma amostra de dados da metade mais baixa. Pode ser entendida como o valor do meio. Com 3 valores, o cálculo é trivial. Podemos também provar que no CASO MÉDIO (para todas as possíveis configurações de pivô), quick sort tem uma complexidade de tempo de O(n log n). Ironicamente, vetores já ordenados (ou quase ordenados) e com o pivô sendo o primeiro (ou o último) elemento representam situações tipo pior caso. Quanto mais balanceada a partição, melhor! Melhoras no algoritmo podem ser feitas no sentido de reduzir a chance de ocorrer o pior caso. Uma idéia é usar um gerador de números aleatórios para pegar um pivô e trocá-lo com o item em v[0]. Outra idéia é encontrar a mediana de 3 elementos (o primeiro, o do fim e o do meio) e trocá-la com o item em v[0] (que passará a ser o pivô). Por exemplo, v= 4,2,8,1,3,6 tem first = v[0]= 4, last = v[5] = 6, middle = v[(0+5)/2] = v[2] = 8, e a mediana é o 6. Selection Sort pode ser mais vantajoso para listas pequenas ( 30) ou quase ordenadas. não use quick sort para arrays pequenos! Portanto, uma idéia é fazer o algoritmo quick sort usar selection sort quando o subvetor tiver tamanho 30 (ou outro limite, e.g. 10). Acredita-se que isto economiza cerca de 15% no tempo de processamento.