]> web.ist.utl.pt Git - iaed.git/commitdiff
Add sort stuff in aula06.
authorA P Francisco <aplf@ist.utl.pt>
Tue, 1 Apr 2014 15:06:26 +0000 (16:06 +0100)
committerA P Francisco <aplf@ist.utl.pt>
Tue, 1 Apr 2014 15:06:26 +0000 (16:06 +0100)
aula06/Makefile [new file with mode: 0644]
aula06/sort.c [new file with mode: 0644]

diff --git a/aula06/Makefile b/aula06/Makefile
new file mode 100644 (file)
index 0000000..22411a0
--- /dev/null
@@ -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 (file)
index 0000000..701c4df
--- /dev/null
@@ -0,0 +1,528 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <time.h>
+
+#include <assert.h>
+
+/* 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]<v avanca com o i para a direita. */
+    while (less(a[++i], v));
+
+    /* Enquanto v<a[j] avanca com o j para a esquerda. */
+    while (less(v, a[--j]))
+      if (j == l) /* O elemento onde se faz a particao pode ser o primeiro! */
+        break;
+
+    /* Trocar, se for o caso! */
+    if (i < j)
+      exch(a[i], a[j]);
+  }
+
+  /* Colocar o pivot na posicao i. */
+  exch(a[i], a[r]);
+
+  /* Retorna posicao onde ocorreu a particao. */
+  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);
+}
+
+#define QM 10
+
+void quicksortM(Item a[], int l, int r) 
+{
+  int i;
+
+  if(r-l <= QM) {
+    insertion(a, l, r);
+    return;
+  }
+
+  i = partition(a, l, r);
+  quicksort(a, l, i-1);
+  quicksort(a, i+1, r);
+}
+
+Item aux[maxN];
+
+void 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[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(&current_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;
+}
+