AED 2002/2003 p.1/22 Algoritmos Eficientes de Ordenação Quick Sort Merge Sort Heap Sort Utilizar informação das chaves: Counting Sort Radix Sort
AED 2002/2003 p.2/22 Quick Sort int partition(item a[], int l, int r) { int i = l-1, j = r; Item v = a[r]; for (;;) { while (less(a[++i], v)) ; while (less(v, a[--j])) if (j == l) break; if (i >= j) break; exch(a[i], a[j]); exch(a[i], a[r]); return i; void quicksort(item a[], int l, int r) { int i; if (r <= l) return; i = partition(a, l, r); quicksort(a, l, i-1); quicksort(a, i+1, r);
AED 2002/2003 p.3/22 Quick Sort Complexidade Complexidade depende das chaves Para array já ordenado, tempo de execução é Normalmente, para qualquer partição razoável do vector a cada passo do algoritmo, complexidade é Não é estável
AED 2002/2003 p.4/22 Merge Sort Item aux[maxn]; merge(item a[], int l, int m, int r) { int i, j, k; for (i = m+1; i > l; i--) aux[i-1] = a[i-1]; for (j = m; j < r; j++) aux[r+m-j] = a[j+1]; for (k = l; k <= r; k++) if (less(aux[i], aux[j])) a[k] = aux[i++]; else a[k] = aux[j--]; void mergesort(item a[], int l, int r) { int m = (r+l)/2; if (r <= l) return; mergesort(a, l, m); mergesort(a, m+1, r); merge(a, l, m, r);
AED 2002/2003 p.5/22 Merge Sort Complexidade Tempo de execução: Fácil de verificar quando geral recorrendo a indução Complexidade pior caso é é potência de 2, e no caso É estável
AED 2002/2003 p.6/22 Merge Sort Bottom-Up #define min(a, B) (A < B)? A : B void mergesortbu(item a[], int l, int r) { int i, m; for (m = 1; m < r-l; m = m+m) for (i = l; i <= r-m; i += m+m) merge(a, i, i+m-1, min(i+m+m-1, r));
Merge Sort com Listas link merge(link a, link b) { struct node head; link c = &head; while ((a!= NULL) && (b!= NULL)) if (less(a->item, b->item)) { c->next = a; c = a; a = a->next; else { c->next = b; c = b; b = b->next; c->next = (a == NULL)? b : a; return head.next; link mergesort(link c) { link a, b; if (c->next == NULL) return c; a = c; b = c->next; while ((b!= NULL) && (b->next!= NULL)) { c = c->next; b = b->next->next; b = c->next; c->next = NULL; return merge(mergesort(a), mergesort(b)); AED 2002/2003 p.7/22
AED 2002/2003 p.8/22 Heap Sort #define pq(a) a[l-1+a] void heapsort(item a[], int l, int r) { int k, N = r-l+1; for (k = N/2; k >= 1; k--) fixdown(&pq(0), k, N); while (N > 1) { exch(pq(1), pq(n)); fixdown(&pq(0), 1, --N);
AED 2002/2003 p.9/22 Heap Sort Complexidade Construção do amontoado (ciclo for): no pior caso É possível assegurar Colocação das chaves (ciclo while): no pior caso Complexidade pior caso é Não é estável
AED 2002/2003 p.10/22 Avaliação Experimental N Quick Merge Heap 12500 2 5 3 25000 7 11 8 50000 13 24 18 100000 27 52 42 200000 58 111 100 400000 122 238 232 800000 261 520 542
AED 2002/2003 p.11/22 Ordenação por Comparação Algoritmos de ordenação baseados em comparações são Para chaves existem ordenações possíveis das chaves Algoritmo de ordenação por comparação utiliza comparações de pares de chaves para seleccionar uma das ordenações Escolher uma folha em árvore com Altura da árvore é não inferior folhas É possível obter algoritmos mais eficientes desde que não sejam baseados em comparações: Utilizar informação quanto às chaves utilizadas Counting Sort Radix Sort
AED 2002/2003 p.12/22 Counting Sort Motivação Ordenar Chaves podem tomar valor entre 0 e Se existem primeiras Se existem posições... chaves com valor 0, então ocupam as posições do array final, 0 a! a chaves com valor 1, então ocupam as posições do array final! Necessário vectores auxiliares para guardar contagens e para construir array ordenado
AED 2002/2003 p.13/22 Counting Sort I void distcount(int a[], int l, int r) { int i, j, cnt[m+1]; int b[maxn]; for (j = 0; j <= M; j++) cnt[j] = 0; for (i = l; i <= r; i++) cnt[a[i]+1]++; for (j = 1; j < M; j++) cnt[j] += cnt[j-1]; for (i = l; i <= r; i++) b[cnt[a[i]]++] = a[i]; for (i = l; i <= r; i++) a[i] = b[i];
AED 2002/2003 p.14/22 Counting Sort Complexidade Dois ciclos relativos à dimensão das chaves Três ciclos relativos às Complexidade: chaves
AED 2002/2003 p.15/22 Counting Sort II void distcount(int a[], int l, int r) { int i, j, cnt[m]; int b[maxn]; for (j = 0; j < M; j++) cnt[j] = 0; for (i = l; i <= r; i++) cnt[a[i]]++; for (j = 1; j < M; j++) cnt[j] += cnt[j-1]; for (i = r; i >= l; i--) b[--cnt[a[i]]] = a[i]; for (i = l; i <= r; i++) a[i] = b[i]; Diferenças?? Definição do valor cnt[j] Estabilidade do algoritmo??
AED 2002/2003 p.16/22 Radix Sort Definições #define bitsword 32 #define bitsbyte 8 #define bytesword 4 #define R (1 << bitsbyte) #define digit(a, B) (((A) >> (bitsword-((b)+1)*bitsbyte)) & (R-1))
AED 2002/2003 p.17/22 Radix Sort I #define bin(a) l+count[a] void radixmsd(item a[], int l, int r, int w) { int i, j, count[r+1]; if (w > bytesword) return; if (r-l <= M) { insertion(a, l, r); return; for (j = 0; j < R; j++) count[j] = 0; for (i = l; i <= r; i++) count[digit(a[i], w) + 1]++; for (j = 1; j < R; j++) count[j] += count[j-1]; for (i = l; i <= r; i++) aux[l+count[digit(a[i], w)]++] = a[i]; for (i = l; i <= r; i++) a[i] = aux[i]; radixmsd(a, l, bin(0)-1, w+1); for (j = 0; j < R-1; j++) radixmsd(a, bin(j), bin(j+1)-1, w+1);
AED 2002/2003 p.18/22 Radix Sort I Operação Utilizar dígitos, do maior peso para o menor peso: Colocar chaves em caixas Ordenar elementos de cada caixa utilizando dígitos subsequentes Se número de elementos não superior a, utilizar insertion sort
AED 2002/2003 p.19/22 Radix Sort II void radixlsd(item a[], int l, int r) { int i, j, w, count[r+1]; for (w = bytesword-1; w >= 0; w--) { for (j = 0; j < R; j++) count[j] = 0; for (i = l; i <= r; i++) count[digit(a[i], w) + 1]++; for (j = 1; j < R; j++) count[j] += count[j-1]; for (i = l; i <= r; i++) aux[count[digit(a[i], w)]++] = a[i]; for (i = l; i <= r; i++) a[i] = aux[i];
AED 2002/2003 p.20/22 Radix Sort II Operação Utilizar dígitos, do menor peso para o maior peso: Ordenar todo o vector utilizando counting sort utilizando cada dígito
& $ AED 2002/2003 p.21/22 Eficiência dos Radix Sorts Radix Sort I Tempo de execução cresce com número de bytes dos elementos a ordenar Radix Sort II, para chaves com Espaço adicional: contadores & % $ #" bits
AED 2002/2003 p.22/22 Avaliação Experimental N Quick MSD LSD 12500 2 28 4 25000 5 29 8 50000 10 35 18 100000 21 47 39 200000 49 72 81 400000 102 581 169 800000 223 6064 328