Algoritmos Elementares de Ordenação Selection Sort Insertion Sort Bubble Sort Shell Sort Counting Sort AED 2002/2003 – p.1/19 Algoritmos de Sort – Definições #define key(A) (A) #define less(A, B) (key(A) < key(B)) #define exch(A, B) { Item t = A; A = B; B = t; } #define compexch(A, B) if (less(B, A)) exch(A, B) AED 2002/2003 – p.2/19 Algoritmos de Sort – Utilização void sort(Item a[], int l, int r) { int i, j; for (i = l+1; i <= r; i++) for (j = i; j > l; j--) compexch(a[j-1], a[j]); } main(int argc, char *argv[]) { int i, N = atoi(argv[1]), sw = atoi(argv[2]); int *a = malloc(N*sizeof(int)); if (sw) for (i = 0; i < N; i++) a[i] = 1000*(1.0*rand()/RAND_MAX); else while (scanf("%d", &a[N]) == 1) N++; sort(a, 0, N-1); for (i = 0; i < N; i++) printf("%3d ", a[i]); printf("\n"); } Exemplo: AED 2002/2003 – p.3/19 Selection Sort void selection(Item a[], int l, int r) { int i, j; for (i = l; i < r; i++) { int min = i; for (j = i+1; j <= r; j++) if (less(a[j], a[min])) min = j; exch(a[i], a[min]); } } Exemplo: AED 2002/2003 – p.4/19 Selection Sort A cada passo, escolher o menor entre os maiores elementos. , com , com Tempo de execução: No pior caso é No melhor caso, é Para cada valor de do primeiro ciclo, segundo ciclo é vezes executado Algoritmo é estável i.e. ordem relativa de chaves duplicadas é mantida AED 2002/2003 – p.5/19 Insertion Sort void insertion(Item a[], int l, int r) { int i; for (i = l+1; i <= r; i++) compexch(a[l], a[i]); for (i = l+2; i <= r; i++) { int j = i; Item v = a[i]; while (less(v, a[j-1])) { a[j] = a[j-1]; j--; } a[j] = v; } } Exemplo: AED 2002/2003 – p.6/19 Insertion Sort Primeiro ciclo coloca menor valor na posição , o qual depois serve como sentinela reduz constantes do segundo ciclo , i.e. vector já , i.e. vector já Tempo de execução: No pior caso, é , com ordenado por ordem inversa No melhor caso é , com ordenado Para cada , os primeiros elementos ficam ordenados Algoritmo é estável AED 2002/2003 – p.7/19 Bubble Sort void bubble(Item a[], int l, int r) { int i, j; for (i = l; i < r; i++) for (j = r; j > i; j--) compexch(a[j-1], a[j]); } Exemplo: AED 2002/2003 – p.8/19 Bubble Sort Para cada valor de no primeiro ciclo, segundo ciclo é vezes executado , com , com Tempo de execução: No pior caso é No melhor caso é Para cada valor de , algoritmo assegura que valor final na posição é o valor certo para a posição após vector ordenado Algoritmo é estável AED 2002/2003 – p.9/19 Comparação Pior Caso Comparações Trocas Chaves Selection Insertion Bubble AED 2002/2003 – p.10/19 Avaliação Experimental N Selection Insertion Bubble 1000 5 4 11 2000 21 15 45 4000 85 62 182 AED 2002/2003 – p.11/19 Shell Sort – Definições Vector diz-se -ordenado se qualquer sequência de números separados por posições está ordenada Vector 1 15 2 16 3 17 4 18 5 19 está 2-ordenado O resultado de -ordenar um vector que está -ordenado, é um vector que está -ordenado e -ordenado AED 2002/2003 – p.12/19 Shell Sort – Algoritmo void shellsort(Item a[], int l, int r) { int i, j, h; for (h = 1; h <= (r-l)/9; h = 3*h+1) ; for ( ; h > 0; h /= 3) for (i = l+h; i <= r; i++) { int j = i; Item v = a[i]; while (j >= l+h && less(v, a[j-h])) { a[j] = a[j-h]; j -= h; } a[j] = v; } } Segundo ciclo for é executado para os valores de ordem inversa Primeiro ciclo for gera sequência: 1 4 13 40 121 364 1093 3280 ... por AED 2002/2003 – p.13/19 Shell Sort – Funcionamento Operação (vector com tamanho 100): Para cada valor de , 40, 13, 4, 1: Utilizar insertion sort para criar sub-vectores ordenados dentro de vector com tamanho 100 · Vector fica -ordenado Para 40 existem 40 sub-vectores ordenados, cada um com 2/3 elementos Para 13 existem 13 sub-vectores ordenados, cada um com 7/8 elementos ... Para 1 existe 1 (sub-)vector ordenado, com 100 elementos AED 2002/2003 – p.14/19 Shell Sort – Exemplo void shellsort(Item a[], int l, int r) { int i, j, h; for (h = 1; h <= (r-l)/9; h = 3*h+1) ; for ( ; h > 0; h /= 3) for (i = l+h; i <= r; i++) { int j = i; Item v = a[i]; while (j >= l+h && less(v, a[j-h])) { a[j] = a[j-h]; j -= h; } a[j] = v; } } Exemplo: AED 2002/2003 – p.15/19 Shell Sort – Complexidade Complexidade depende da sequência de valores utilizada: Sequência 1, 4, 13, 40, 121, 364, 1093, ... comparações Sequência 1, 8, 23, 77, 281, 1073, 4193, ... comparações Sequência 1, 2, 3, 4, 6, 9, 8, 12, 18, 27, 16, 24, ... comparações AED 2002/2003 – p.16/19 Avaliação Experimental – Shell Sort N O K G S P I 12500 16 6 6 5 6 6 25000 37 13 11 12 15 10 50000 102 31 30 27 38 26 100000 303 77 60 63 81 58 200000 817 178 137 139 180 126 O: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, ... K: 1, 4, 13, 40, 121, 364, ... G: 1, 2, 4, 10, 23, 51, 113, 249, 548, ... S: 1, 8, 23, 77, 281, ... P: 1, 7, 8, 49, 56, 64, 343, 392, 448, 512, ... I: 1, 5, 19, 41, 109, 209, 505, 929, ... AED 2002/2003 – p.17/19 Utilização de Listas – Interface typedef struct node *link; struct node { Item item; link next; }; link NEW(Item, link); link init(int); void show(link); link sort(link); AED 2002/2003 – p.18/19 Utilização de Listas – Selection Sort link listselection(link h) { link max, t, out = NULL; while (h->next != NULL) { max = findmax(h); t = max->next; max->next = t->next; t->next = out; out = t; } h->next = out; return(h); } A cada passo retira máximo elemento de lista actual, e coloca no topo da nova lista AED 2002/2003 – p.19/19