From: A P Francisco Date: Tue, 1 Apr 2014 15:06:26 +0000 (+0100) Subject: Add sort stuff in aula06. X-Git-Url: http://web.ist.utl.pt/aplf/git/?a=commitdiff_plain;h=5cd05cdd26759d5b0823d3f2e1da77f1e03e3d8b;p=iaed.git Add sort stuff in aula06. --- diff --git a/aula06/Makefile b/aula06/Makefile new file mode 100644 index 0000000..22411a0 --- /dev/null +++ b/aula06/Makefile @@ -0,0 +1,12 @@ +CC=gcc +CFLAGS=-O3 -Wall -ansi -pedantic + +EXECS=sort + +all: ${EXECS} + +livros: sort.o + gcc ${CFLAGS} -o $@ $< + +clean: + rm -f *.o ${EXECS} diff --git a/aula06/sort.c b/aula06/sort.c new file mode 100644 index 0000000..701c4df --- /dev/null +++ b/aula06/sort.c @@ -0,0 +1,528 @@ +#include +#include +#include + +#include + +#include + +/* ATENCAO AOS VARIOS #define ESPECIFIOS DE CADA ALGORITMO */ + +typedef int Item; +#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) + +#define N 100000 +#define maxN 1000000 +#define M 100000 + +void selection(Item a[], int l, int r) +{ + int i, j, min; + for (i = l; i < r; i++) { + min = i; + for (j = i+1; j <= r; j++) + if (less(a[j], a[min])) + min = j; + exch(a[i], a[min]); + } +} + +void insertion(Item a[], int l, int r) +{ + int i; + + /* Coloca menor elemento na primeira posicao */ + for (i = l+1; i <= r; i++) + compexch(a[l], a[i]); + + for (i = l+2; i <= r; i++) { + int j = i; + + /* Variavel auxiliar para guardar o valor a[i] */ + Item v = a[i]; + + /* Enquanto v < a[j] puxar os valores para a direita */ + /* Como o primeiro elemento e' o menor podemos omitir a condicao j>=l */ + while (less(v, a[j-1])) { + a[j] = a[j-1]; + j--; + } + + /* Guardar o valor originalmente na posicao i na posicao libertada */ + a[j] = v; + } +} + +void bubble(Item a[], int l, int r) +{ + int i, j, done; + for (i = l; i < r; i++){ + done=1; + for (j = r; j > i; j--) + if (less(a[j], a[j-1])){ + exch(a[j-1], a[j]); + done=0; + } + if (done) break; + } +} + +void shellsort(Item a[], int l, int r) +{ + int i, j, h; + Item v; + + /* 1, 4, 13, 40, 121, 364, 1093, 3280, ... */ + for (h = 1; h <= (r-l)/9; h = 3*h+1) + ; + + /* Execucao para os valores de h, por ordem inversa. */ + for ( ; h > 0; h /= 3) { + + /* Insertion sort com saltos de tamanho h. */ + for (i = l+h; i <= r; i++) { + j = i; + v = a[i]; + + while (j >= l+h && less(v, a[j-h])) { + a[j] = a[j-h]; + j -= h; + } + a[j] = v; + } + } +} + +int partition(Item a[], int l, int r) { + int i = l-1; + int j = r; + + /* a[r] 'e o pivot. */ + Item v = a[r]; + + /* Enquanto o iterador da esquerda for menor que o iterador da direita. */ + while (i < j) { + + /* Enquanto a[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[j], aux[i])) + a[k] = aux[j--]; + else + a[k] = aux[i++]; +} + +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); +} + +#define LEFT(x) (((x) << 1) + 1) +#define RIGHT(x) (((x) + 1) << 1) +#define PARENT(x) ((((x) + 1) >> 1) - 1) + +void fixDown(Item a[], int l, int r, int k) +{ + int ileft, iright, largest=k; + + ileft=l+LEFT(k-l); + iright=l+RIGHT(k-l); + + if (ileft<=r && less(a[largest],a[ileft])) + largest=ileft; + if (iright<=r && less(a[largest],a[iright])) + largest=iright; + + if (largest!=k){ + exch(a[k],a[largest]); + fixDown(a, l, r, largest); + } +} + +void buildheap(Item a[], int l, int r){ + int k, heapsize = r-l+1; + for (k = heapsize/2-1; k >= l; k--) + fixDown(a, l, r, l+k); +} + +void heapsort(Item a[], int l, int r) { + buildheap(a,l,r); + while (r-l > 0) { + exch(a[l], a[r]); + fixDown(a, l, --r, l); + } +} + +/* + * int a[] + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * | 5 | 2 | 1 | 6 | 5 | 3 | 3 | 4 | 0 | 1 | 2 | 4 | 6 | 0 | 4 | 6 | 3 | 1 | + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * l r + * + * N = r-l+1 = 18 e M = 7 + */ +void distcount(int a[], int l, int r) +{ + int i, j, cnt[M+1]; + int b[maxN]; + + /* + * Inicializar cnt[M+1] a 0 + * +----+----+----+----+----+----+----+----+ + * | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | + * +----+----+----+----+----+----+----+----+ + */ + for (j = 0; j <= M; j++) + cnt[j] = 0; + + /* + * Contar elementos em a[], cnt[a[i]+1] fica com o numero de ocorrencias de a[i] + * +----+----+----+----+----+----+----+----+ + * | 0 | 2 | 3 | 2 | 3 | 3 | 2 | 3 | + * +----+----+----+----+----+----+----+----+ + */ + for (i = l; i <= r; i++) + cnt[a[i]+1]++; + + /* + * Acumular valores em cnt[] por forma a que cnt[i] indique a posicao final de i + * +----+----+----+----+----+----+----+----+ + * | 0 | 2 | 5 | 7 | 10 | 13 | 15 | 18 | + * +----+----+----+----+----+----+----+----+ + */ + for (j = 1; j < M; j++) + cnt[j] += cnt[j-1]; + + /* + * Guardar em {{{b}}} os valores de {{{a}}} ordenados + * + * int cnt[] + * +----+----+----+----+----+----+----+----+ + * | 2 | 5 | 7 | 10 | 13 | 15 | 18 | 18 | + * +----+----+----+----+----+----+----+----+ + * + * int b[] + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * | 0 | 0 | 1 | 1 | 1 | 2 | 2 | 3 | 3 | 3 | 4 | 4 | 4 | 5 | 5 | 6 | 6 | 6 | + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * + * Notar que cnt[] e' actualizado 'a medida que são colocados os elementos em b[] + */ + for (i = l; i <= r; i++) + b[cnt[a[i]]++] = a[i]; + + /* + * Copiar {{{b}}} para {{{a}}} + * + * int a[] + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * | 0 | 0 | 1 | 1 | 1 | 2 | 2 | 3 | 3 | 3 | 4 | 4 | 4 | 5 | 5 | 6 | 6 | 6 | + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + */ + for (i = l; i <= r; i++) + a[i] = b[i - l]; +} + +void distcount2(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 - l]; +} + +#define bitsword 32 +#define bitsbyte 8 +#define bytesword 4 +#define digit(n,w) (0xff & ((n) >> ((bytesword - (w) - 1) << 3))) +#define nbit(n,w) (0x01 & ((n) >> (bitsword - (w) - 1))) + +/* Numero de valores possiveis para um digito */ +#define R (1 << bitsbyte) + +Item aux[maxN]; + +void radixLSD(Item a[], int l, int r) +{ + int i, j, w, count[R+1]; + for (w = bytesword-1; w >= 0; w--) { + + /* Counting sort para o digito 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 - l]; + } +} + +void quicksortB(int a[], int l, int r, int w) +{ + int i = l, j = r; + if (r <= l || w >= bitsword) + return; + + /* Particiona o vector em duas áreas: + * - chaves com bit w a 0 + * - chaves com bit w a 1 + */ + while (j != i) { + while (nbit(a[i], w) == 0 && (i < j)) i++; + while (nbit(a[j], w) == 1 && (j > i)) j--; + exch(a[i], a[j]); + } + if (nbit(a[r], w) == 0) + j++; + + /* Ordena recursivamente cada área */ + quicksortB(a, l, j-1, w+1); + quicksortB(a, j, r, w+1); +} + +#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; + + /* Optimizacao */ + if (r-l <= QM) { + insertion(a, l, r); + return; + } + + /* Counting sort para o digito 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 - l]; + + /* Os bins denotam as caixas discutidas acima */ + 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); +} + +int +intcmp(const void * x, const void * y) +{ + return *((const int *) x) - *((const int *) y); +} + +int diff(int a[], int an, int b[], int bn) +{ + int i; + + if (an != bn) + return 1; + + for (i = 0; i < an; i++) + if (a[i] != b[i]) + return 1; + + return 0; +} + +void +timedlog(char *t) +{ + time_t current_time; + char* c_time_string; + + current_time = time(NULL); + c_time_string = ctime(¤t_time); + c_time_string[strlen(c_time_string) - 1] = '\0'; + + printf("[%s] %s\n", c_time_string, t); +} + +int +main(int argc, char *argv[]) +{ + int i, a[N], r[N], s[N]; + + if (argc > 1) + srand(atoi(argv[1])); + + for (i = 0; i < N; i++) { + a[i] = (M-1)*(1.0*rand()/RAND_MAX); + assert(a[i] < M); + } + + timedlog("running qsort"); + memcpy(r, a, sizeof(int)*N); + assert(!diff(a, N, r, N)); + qsort(r, N, sizeof(int), intcmp); + + timedlog("testing selectionsort"); + memcpy(s, a, sizeof(int)*N); + assert(!diff(a, N, s, N)); + selection(s, 0, N-1); + assert(!diff(r, N, s, N)); + + timedlog("testing insertionsort"); + memcpy(s, a, sizeof(int)*N); + assert(!diff(a, N, s, N)); + insertion(s, 0, N-1); + assert(!diff(r, N, s, N)); + + timedlog("testing bubblesort"); + memcpy(s, a, sizeof(int)*N); + assert(!diff(a, N, s, N)); + bubble(s, 0, N-1); + assert(!diff(r, N, s, N)); + + timedlog("testing shellsort"); + memcpy(s, a, sizeof(int)*N); + assert(!diff(a, N, s, N)); + shellsort(s, 0, N-1); + assert(!diff(r, N, s, N)); + + timedlog("testing quicksort"); + memcpy(s, a, sizeof(int)*N); + assert(!diff(a, N, s, N)); + quicksort(s, 0, N-1); + assert(!diff(r, N, s, N)); + + timedlog("testing quicksort+insertionsort"); + memcpy(s, a, sizeof(int)*N); + assert(!diff(a, N, s, N)); + quicksortM(s, 0, N-1); + assert(!diff(r, N, s, N)); + + timedlog("testing mergesort"); + memcpy(s, a, sizeof(int)*N); + assert(!diff(a, N, s, N)); + mergesort(s, 0, N-1); + assert(!diff(r, N, s, N)); + + timedlog("testing heapsort"); + memcpy(s, a, sizeof(int)*N); + assert(!diff(a, N, s, N)); + heapsort(s, 0, N-1); + assert(!diff(r, N, s, N)); + + timedlog("testing countingsort"); + memcpy(s, a, sizeof(int)*N); + assert(!diff(a, N, s, N)); + distcount(s, 0, N-1); + assert(!diff(r, N, s, N)); + + timedlog("testing countingsort (2)"); + memcpy(s, a, sizeof(int)*N); + assert(!diff(a, N, s, N)); + distcount2(s, 0, N-1); + assert(!diff(r, N, s, N)); + + timedlog("testing radixLSD"); + memcpy(s, a, sizeof(int)*N); + assert(!diff(a, N, s, N)); + radixLSD(s, 0, N-1); + assert(!diff(r, N, s, N)); + + timedlog("testing radixMSD"); + memcpy(s, a, sizeof(int)*N); + assert(!diff(a, N, s, N)); + radixMSD(s, 0, N-1, 0); + assert(!diff(r, N, s, N)); + + timedlog("testing binary quicksort"); + memcpy(s, a, sizeof(int)*N); + assert(!diff(a, N, s, N)); + quicksortB(s, 0, N-1, 0); + assert(!diff(r, N, s, N)); + + /* + for (i = 0; i < N; i++) + printf("a[%3d] = %3d\n", i, a[i]); + */ + + return EXIT_SUCCESS; +} +