Proyecto de ordenamiento para el curso de Análisis y Diseño de Algoritmos.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

bitonic_sort.c 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /*
  2. * Copyright 2018 Christopher Cromer
  3. * Copyright 2018 Rodolfo Cuevas
  4. *
  5. * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
  6. *
  7. * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  8. *
  9. * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  10. *
  11. * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
  12. *
  13. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14. */
  15. /**
  16. * Verificar si x es de 2^n
  17. * @param x El valor a verificar
  18. * @return Retorna 1 si es de 2^n ó 0 al contrario;
  19. */
  20. int power_of_two(int n) {
  21. if (n == 0) {
  22. return 0;
  23. }
  24. while (n != 1) {
  25. if (n % 2 != 0) {
  26. return 0;
  27. }
  28. n = n / 2;
  29. }
  30. return 1;
  31. }
  32. /**
  33. * Buscar un valor que es de potencia de 2 pero menor que n
  34. * @param n El valor de n
  35. * @return Un potencia de 2 que es menor que n
  36. */
  37. int greatest_power_of_two_less_than(int n) {
  38. int k = 1;
  39. while (k > 0 && k < n) {
  40. k = (int) ((unsigned int) k << 1);
  41. }
  42. k = (int) ((unsigned int) k >> 1);
  43. return (int) k;
  44. }
  45. /**
  46. * Comparar y intercambiar los valores para darle orden
  47. * @param i El primer indice a comparar
  48. * @param j El segundo indice a comparar
  49. * @param dir La dirección a ordenar, 1 para ascendentemente o 0 por descendentamente
  50. * @param array El array a ordenar
  51. */
  52. void compare(int i, int j, int dir, int *array) {
  53. int temp;
  54. if (dir == (array[i] > array[j])){
  55. temp = array[i];
  56. array[i] = array[j];
  57. array[j] = temp;
  58. }
  59. }
  60. /**
  61. * Unir la secuencia
  62. * @param low El parte inferior
  63. * @param c El parte superior n
  64. * @param dir La dirección a ordenar, 1 para ascendentemente o 0 por descendentamente
  65. * @param array El array a ordenar
  66. */
  67. void bitonicmerge(int low, int n, int dir, int *array) {
  68. int i;
  69. int k;
  70. if (n > 1) {
  71. k = n / 2;
  72. for (i = low; i < low + k; i++){
  73. compare(i, i + k, dir, array);
  74. }
  75. bitonicmerge(low, k, dir, array);
  76. bitonicmerge(low + k, k, dir, array);
  77. }
  78. }
  79. /**
  80. * Unir la secuencia cuando n no es de potencia 2
  81. * @param low El parte inferior
  82. * @param c El parte superior n
  83. * @param dir La dirección a ordenar, 1 para ascendentemente o 0 por descendentamente
  84. * @param array El array a ordenar
  85. */
  86. void bitonicmerge_no2(int low, int n, int dir, int *array) {
  87. int i;
  88. int k;
  89. if (n > 1) {
  90. k = greatest_power_of_two_less_than(n);
  91. for (i = low; i < low + n-k; i++){
  92. compare(i, i + k, dir, array);
  93. }
  94. bitonicmerge_no2(low, k, dir, array);
  95. bitonicmerge_no2(low + k, n - k, dir, array);
  96. }
  97. }
  98. /**
  99. * Generar la secuencia bitonica en forma de piramide
  100. * @param low El parte inferior
  101. * @param c El parte superior n
  102. * @param dir La dirección a ordenar, 1 para ascendentemente o 0 por descendentamente
  103. * @param array El array a ordenar
  104. */
  105. void recbitonic(int low, int n, int dir, int *array) {
  106. int k;
  107. if (n > 1) {
  108. k = n / 2;
  109. recbitonic(low, k, 1, array);
  110. recbitonic(low + k, k, 0, array);
  111. bitonicmerge(low, n, dir, array);
  112. }
  113. }
  114. /**
  115. * Generar la secuencia bitonica en forma de piramide cuando n no es de potencia 2
  116. * @param low El parte inferior
  117. * @param c El parte superior n
  118. * @param dir La dirección a ordenar, 1 para ascendentemente o 0 por descendentamente
  119. * @param array El array a ordenar
  120. */
  121. void recbitonic_no2(int low, int n, int dir, int *array) {
  122. int k;
  123. if (n > 1){
  124. k = n / 2;
  125. recbitonic_no2(low, k, !dir, array);
  126. recbitonic_no2(low + k, n - k, dir, array);
  127. bitonicmerge_no2(low, n, dir, array);
  128. }
  129. }
  130. /**
  131. * Ordenar el arreglo completo
  132. * @param array El array a ordenar
  133. * @param n El tamaño del array
  134. * @param dir La dirección a ordenar, 1 para ascendentemente o 0 por descendentamente
  135. */
  136. void sort(int *array, int n, int dir) {
  137. if (power_of_two(n)) {
  138. recbitonic(0, n, dir, array);
  139. }
  140. else {
  141. recbitonic_no2(0, n, dir, array);
  142. }
  143. }
  144. /**
  145. * Usar el algoritmo de bitonic sort
  146. * @param array El array a ordenar
  147. * @param n El tamaño del array
  148. */
  149. void bitonic_sort(int *array, int n) {
  150. sort(array, n, 1);
  151. }