1 / 27

Métodos de Ordenação

Métodos de Ordenação. Desempenho, Método de Shell, Quick sort. Análise de Desempenho. A análise de desempenho visa determinar uma função (f) que permita computar o tempo gasto por um algoritmo. F é função do tamanho da entrada do algoritmo. Exemplo.

erna
Download Presentation

Métodos de Ordenação

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Métodos de Ordenação Desempenho, Método de Shell, Quicksort

  2. Análise de Desempenho • A análise de desempenho visa determinar uma função (f) que permita computar o tempo gasto por um algoritmo. • F é função do tamanho da entrada do algoritmo

  3. Exemplo Determinar a função de desempenho da função troca vetores: void trocavetores(int a[],int b[], int n) { int i; for(i=0;i<n;i++) troca(&a[x],&b[x]); }

  4. Desempenho • Atribuir custo às operações usadas no algoritmo: void trocavetores(int a[],int b[], int n) { int i; n for(i=0;i<n;i++) 1 troca(&a[x],&b[x]); } 2. Considerar os loops multiplicando os custos: f(n) = n * 1

  5. Desempenho • Considerar só as operações relevantes para o desempenho. Operações podem ser desprezadas se forem insiginificantes com relação as operações relevantes: void trocavetores(int a[],int b[], int n) { int i,x,y; n for(i=0;i<n;i++){ 0 x=a[i]; 0 y=b[i] 1 troca(&x,&y); 0 a[i]=x; 0 b[i]=y; } f(n) = n * 1

  6. Desempenho • Um loop dentro de outro void leMatrizQuadrada(int m[MAX][MAX], int n, FILE *arq){ int i,j; n for(i=0;i<n;i++) { n for(j=0;j<n;j++) { 1 fscanf(arq,”%d”, &m[i][j]); } } f(n) = n*n*1 = n2

  7. Desempenho • Em algoritmos de ordenação f é determinada em função do tamanho do vetor • As operações relevantes são as comparações e trocas

  8. Desempenho método da seleção algoritmo seleção (int a[], int n){ L1 Para i da primeira posição até a penúltima faca 0 mínimo = i L2 para j da posição seguinte a i até a ultima posição faça 1 se (a[j] < a[mínimo] minimo =j; fim para 1troca(a[mínimo],a[i]); fim para fim algoritmo L1 = n-1 L2 = (n-1) + (n-2) + .. + 1 = n*(n-1)/2 F(n) = (n*(n-1)/2)*1 + (n-1)*1 F(n) = n*(n-1)/2 + (n-1)

  9. Desempenho Método da Inserção Algoritmo insercao(int A[], int n) (n-1) para j do segundo elemento até o último faça x = A[j]; i=j-1; (???) enquanto (i >= 0 e A[i] > x) faça A[i+1]=A[i]; i = i-1; fim enquanto A[i+1]=x; fim para fim algoritmo 1

  10. Desempenho Método da Inserção • Em algoritmo como o método da inserção (devido ao loop mais interno) o desempenho não depende somente do tamanho da entrada, depende também do formato da entrada. • Neste caso o formato é: o vetor já está ordenado, está parcialmente ordenado, invertido, formato aleatório. • Nestes casos temos que considerar: • O melhor caso • O pior caso • O caso médio

  11. Desempenho Método da Inserção • Calculando o custo do loop mais interno. Ci é o custo deste loop na i-ésima interação do loop mais externo: • Melhor caso: Ci(n) = 1, • Pior caso: Ci(n) = i, • Caso Médio: Ci(n) = 1 / i * (1 +2 + ...+ i) = (i+1)/2 • Ex: i = 2, = ½ *(1+2), 50% de chance haver uma interação e 50% de chance de haver duas interações.

  12. Desempenho Método da Inserção • F(n) = C2 + C3 + .. + Cn • Calculando o valor de f, temos que considerar os 3 casos: • Melhor Caso: f(n) = (1 + 1 + .. + 1) = n-1 • Pior caso: f(n) = (2 + 3 + 4 .. + n) = n2/2 + n/2 –1 • Caso médio: f(n) = ½ (3 + 4 + .. n +1) = n2/4 + 3n/4 -1

  13. Desempenho Método da Bolha algoritmo bolha ( int a[],int n) L1 Para i do ultimo elemento até o segundo faça L2 para j do segundo elemento até i faça 1 se (a[j-1]>a[j]) 1 troca(&a[j-1],&a[j]); } Melhor caso: f(n) = n2/2 Pior caso: f(n) = 2 n2 Caso médio: f(n) = 5n2/2 Observação: Vejam a implementação do bolha em Assembly em http://pt.wikipedia.org/wiki/Bubble_sort#Assembly Não é fácil programar em C? 

  14. Exercício • Obter as expressões do pior, melhor e caso médio para o método da bolha.

  15. Método de Shell (Shell Sort) • Método inventado por Shell. • Consiste em aplicar o método de inserção em elementos não adjacentes do vetor. • Algoritmo: • Inicialmente, é determinada uma distância d. • Todos os elementos localizados no vetor separados por uma distância d são ordenados. • A cada iteração a distância d é reduzida de acordo com alguma seqüência. • Na ultima iteração esta distância é reduzida a 1. Este passo corresponde ao método de inserção original.

  16. Método de Shell 35 28 16 07 12 08 04 35 está ordenado, 7 é comparado 07 28 16 35 12 08 04 {07,35} está ordenado, 4 é comparado 04 28 16 07 12 08 35 {04,07,35} está ordenado 04 28 16 07 12 08 35 28 está ordenado, 12 é comparado 04 12 16 07 28 08 35 {12,28} está ordenado 04 12 16 07 28 08 35 16 está ordenado, 35 é comparado 04 12 08 07 28 16 35 {08,16} está ordenado Passo 2 : d =1 equivalente ao método da inserção • Exemplo: • Vetor: [35,28,16,07,12,08,04] - • Seqüência de Distâncias: - {3,1}

  17. Método de Shell Algoritmo shell(int A[], int n, int d) para j de d até o último elemento faça x = A[j]; i=j-d; enquanto (i >= 0 e A[i] > x) faça A[i+d]=A[i]; i = i-d; fim enquanto A[i+d]=x; fim para fim algoritmo Quando d = 1 equivale ao algoritmo de inserção: Algoritmo insercao(int A[], int n) para j do segundo elemento até o último faça x = A[j]; i=j-1; enquanto (i >= 0 e A[i] > x) faça A[i+1]=A[i]; i = i-1; fim enquanto A[i+1]=x; fim para fim algoritmo

  18. Método de Shell O algoritmo ordena os elementos separados uma distância d. A distância d é dada por uma seqüência decrescente. Para cada valor de d chamamos o algoritmo shell Exemplo: shellSort1(int a[], int n) { int d[2] = {3,1}; int p,nd =2; for (p=0;p<nd;p++) { shell(a,n,d[p]); } }

  19. Método de Shell • A seqüência {3,1} pode não ter eficiência para grandes vetores. • Não existe uma seqüência ideal. • Donald Knuth mostrou empiricamente que a seqüência ( 1, 4, 13, 40, 121, 364, 1093..) apresenta eficiência 20 % maior que outras seqüências.

  20. Método de Shell • Implementação da seqüência de Knuth: #define MAX xxxxx // tamanho máximo do vetor void shellsort2(int a[],int n) { int i,p=0, d[MAX/9]; if((n/9)<1){ // trata vetores < 9 p =1; d[0]=1; } else { // gera sequencia de knuth no vetor d for (i=1;i<=n/9;i=3*i+1) { d[p] =i; p++; } } for (i=p-1;i>=0;i--) { // executa shell printf("%d \n", d[i]); shell(a,n,d[i]); } }

  21. Método Quicksort (QS) • Baseado na estratégia Dividir para conquistar. • Algoritmo: • Inicialmente, o vetor a[0..n-1] é subdividido em dois vetores • a[0..p] e a [ p+1 .. r] não vazios • cada elemento de a[0..p] é menor ou igual a cada elemento de a[p+1..n-1]. • A[p] é chamado pivô da iteração. • O valor de p é escolhido arbitrariamente. Um escolha trivial é o pivô central p = (esq + dir)/2 • Os dois subvetores a[0..p] e a[p+1..n-1] são ordenados por chamadas recursivas do QS. Ou seja, repete-se o passo 1 para cada um dos subvetores, recursivamente.

  22. Método Quicksort • A operação que divide os elementos do vetor entre maiores e menores que o pivô é chamada de particionamento. • Exemplo: a = { 12, 7, 3, 2, 10, 1, 0}, n =7 , n-1 = 6 particiona (a,0,6) - escolhe o pivô: q = (0+6)/2=3  a[q] = 2 troca 12 com 0 troca 7 com 1 troca 2 com 3 O vetor ficou: {0,1,2,3,10,7,12} Repete o particionamento para a[0..2] e a[3..6]

  23. Método Quicksort a[0..2] = {0,1,2} Particiona(a,0,2) pivô = 1 Não há trocas a[3..6] = {3,10,7,12} Particiona(a,3,6) pivô = q= (3+6)/2 = 4 a[4] = 10 Troca 10 com o 7 No final o vetor está ordenado: {0,1,2,3,7,10,12}

  24. Método Quicksort void particiona(int a[], int esq,int dir, int *pi, int *pj) { int x,i,j; i = esq; j = dir; x = a[(i+j)/2]; // obtém o pivô desta partição faça { procuro por a[i] do lado esquerdo menor que o pivô procuro por um a[j] do lado direito maior que o pivô } se i e j não se cruzarem eu encontrei elementos para trocar troca(a[i],a[j]); avanço o i para depois do elemento trocado avanço o j para antes do elemento trocado } enquanto(i< j); retorno o i e o j para servirem de limites para as novas partições }

  25. Método quicksort void particiona(int a[], int esq,int dir, int *pi, int *pj) { int x,i,j; i = esq; j = dir; x = a[(i+j)/2]; // obtem o pivo desta particao faça { // procuro a[i] > x a esquerda enquanto((x > a[i]) && (i<dir)) { i=i+1 } // procuro a[j] < x a direita enquanto ((x < a[j]) && (j>esq)){ j=j-1 } // se i < = j então eu achei os valores para trocar se(i<=j) { troca(&a[i],&a[j]); i=i+1; j=j-1; } } enquanto(i< j); // retorno os valores de i j *pi = i; *pj = j; }

  26. Método quicksort ordenaQS(int a[], int esq, int dir) { int i,j; particiona(a, esq,dir, &i,&j) se (esq<j) ordenaQS(a,esq,j) se (dir>i) ordenaQS(a,i,dir) } quicksort(int a[],int n) { ordenaQS(a,0,n-1) }

  27. Método quicksort • Desempenho: • Melhor caso: n log( n ) • Caso médio: n log( n ) • Pior caso: n2 • Pesquisa sobre o desempenho do Quicksort, • Fonte – livro referência - Nivio Ziviani – Projeto de algoritmos • http://www.google.com

More Related