00001 /* --------------------------------------------------------------------------- 00002 Phission : 00003 Realtime Vision Processing System 00004 00005 Copyright (C) 2003-2006 Philip D.S. Thoren (pthoren@cs.uml.edu) 00006 University of Massachusetts at Lowell, 00007 Laboratory for Artificial Intelligence and Robotics 00008 00009 This file is part of Phission. 00010 00011 Phission is free software; you can redistribute it and/or modify 00012 it under the terms of the GNU Lesser General Public License as published by 00013 the Free Software Foundation; either version 2 of the License, or 00014 (at your option) any later version. 00015 00016 Phission is distributed in the hope that it will be useful, 00017 but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 GNU Lesser General Public License for more details. 00020 00021 You should have received a copy of the GNU Lesser General Public License 00022 along with Phission; if not, write to the Free Software 00023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00024 00025 ---------------------------------------------------------------------------*/ 00026 #ifdef HAVE_CONFIG_H 00027 #include <phissionconfig.h> 00028 #endif 00029 00030 #include <phStandard.h> 00031 00032 #include <phQuicksort.h> 00033 00034 #include <phError.h> 00035 #include <phMemory.h> 00036 #include <phPrint.h> 00037 00038 #ifdef __cplusplus 00039 extern "C" { 00040 #endif 00041 00042 /* ---------------------------------------------------------------------- */ 00043 int32_t ph_quicksort_partition(const void *arr, 00044 const int32_t low, 00045 const int32_t high, 00046 const uint32_t size, 00047 uint8_t *tempptr, 00048 ph_qs_compare_fn compare 00049 ) 00050 { 00051 uint32_t i = 0; 00052 uint32_t lim = (high - low) + 1; 00053 uint32_t store = low; 00054 const int32_t pivot = (random() % (high - low)) + low; 00055 00056 uint8_t *curptr = ((uint8_t *)arr) + low * size; 00057 uint8_t *pivotptr = ((uint8_t *)arr) + pivot* size; 00058 uint8_t *highptr = ((uint8_t *)arr) + high * size; 00059 uint8_t *storeptr = curptr; 00060 00061 /* If we're down to a parition of size 2, then we only need to compare 00062 * two numbers and don't need to execute the entire body of this 00063 * function */ 00064 if (lim == 2) 00065 { 00066 if (compare(curptr,highptr) > 0) 00067 ph_qsMemswap(curptr,highptr,tempptr,size); 00068 00069 return high; 00070 } 00071 00072 /* Put the pivot value at the end of the partition */ 00073 ph_qsMemswap(highptr,pivotptr,tempptr,size); 00074 00075 /* Loop through all the elements */ 00076 for (i = 0; i < lim - 1; i++ ) 00077 { 00078 /* if i < pivot */ 00079 /* compare returns 0:same, -1:less-than 1:greater-than */ 00080 if (compare(curptr,highptr) <= 0) 00081 { 00082 /* Swap the current value and the one in the store */ 00083 ph_qsMemswap(curptr,storeptr,tempptr,size); 00084 00085 /* Increment the store variables */ 00086 store++; 00087 storeptr += size; 00088 } 00089 curptr += size; 00090 } 00091 00092 /* Bring the pivot value into the correct place within the parition */ 00093 ph_qsMemswap(highptr,storeptr,tempptr,size); 00094 00095 /* Everything above the pivot index is greater in value than the 00096 * pivot and everything below the pivot index is less than or equal to 00097 * the pivot value */ 00098 00099 return store; 00100 } 00101 00102 /* ---------------------------------------------------------------------- */ 00103 void ph_quicksort_recursive( const void *arr, 00104 const int32_t low, 00105 const int32_t high, 00106 const uint32_t size, 00107 uint8_t *tempptr, 00108 ph_qs_compare_fn compare ) 00109 { 00110 if (low < high) 00111 { 00112 int32_t mid = ph_quicksort_partition(arr,low,high,size,tempptr,compare); 00113 00114 ph_quicksort_recursive(arr, low, mid-1,size,tempptr,compare); 00115 ph_quicksort_recursive(arr, mid+1, high, size,tempptr,compare); 00116 } 00117 } 00118 00119 /* ---------------------------------------------------------------------- */ 00120 typedef struct ph_qs_stack_t 00121 { 00122 struct ph_qs_stack_t *next; 00123 int32_t low; 00124 int32_t high; 00125 } ph_qs_stack_type; 00126 00127 /* ---------------------------------------------------------------------- */ 00128 void ph_quicksort_iterative( const void *arr, 00129 const int32_t low, 00130 const int32_t high, 00131 const uint32_t size, 00132 uint8_t *tempptr, 00133 ph_qs_compare_fn compare ) 00134 { 00135 phFUNCTION("ph_quicksort_iterative") 00136 int32_t l = 0; 00137 int32_t h = 0; 00138 int32_t mid = 0; 00139 ph_qs_stack_type *stack_element = NULL; 00140 ph_qs_stack_type *stack = (ph_qs_stack_type *)phMalloc(sizeof(ph_qs_stack_type)); 00141 phCHECK_PTR(stack,"phMalloc", 00142 "phMalloc failed to allocated stack element"); 00143 00144 /* Push the first */ 00145 stack->next = NULL; 00146 stack->low = low; 00147 stack->high = high; 00148 00149 while (stack != NULL) 00150 { 00151 /* Pop */ 00152 stack_element = stack; 00153 stack = stack->next; 00154 l = stack_element->low; 00155 h = stack_element->high; 00156 phFree(stack_element); 00157 00158 if (l < h) 00159 { 00160 /* Partition the array */ 00161 mid = ph_quicksort_partition(arr,l,h,size,tempptr,compare); 00162 00163 /* Push */ 00164 if (l < mid-1) /* Try to avoid as many allocations as possible */ 00165 { 00166 stack_element = (ph_qs_stack_type *)malloc(sizeof(ph_qs_stack_type)); 00167 phCHECK_PTR(stack_element,"phMalloc", 00168 "phMalloc failed to allocated stack element"); 00169 stack_element->next = stack; 00170 stack_element->low = l; 00171 stack_element->high = mid-1; 00172 stack = stack_element; 00173 } 00174 00175 /* Push */ 00176 if (mid+1 < h) /* Try to avoid as many allocations as possible */ 00177 { 00178 stack_element = (ph_qs_stack_type *)malloc(sizeof(ph_qs_stack_type)); 00179 phCHECK_PTR(stack_element,"phMalloc", 00180 "phMalloc failed to allocated stack element"); 00181 stack_element->next = stack; 00182 stack_element->low = mid+1; 00183 stack_element->high = h; 00184 stack = stack_element; 00185 } 00186 } 00187 } 00188 00189 error: 00190 return; 00191 } 00192 00193 /* ---------------------------------------------------------------------- */ 00194 int32_t ph_qs_compare_uint32_t(const void *_one, const void *_two) 00195 { 00196 uint32_t one = *((uint32_t *)_one); 00197 uint32_t two = *((uint32_t *)_two); 00198 00199 /* Greater than : 1 */ 00200 if (one > two) 00201 { 00202 /* printf( "%u > %u\n",one,two); */ 00203 return 1; 00204 } 00205 00206 /* Less than : -1 */ 00207 if (one < two) 00208 { 00209 /* printf( "%u < %u\n",one,two); */ 00210 return -1; 00211 } 00212 00213 /* Equal : 0 */ 00214 /* printf( "%u == %u\n",one,two); */ 00215 return phSUCCESS; 00216 } 00217 00218 /* ---------------------------------------------------------------------- */ 00219 int32_t ph_qs_sort_uint32_t( const uint32_t nelements, 00220 uint32_t *array, 00221 const uint32_t method ) 00222 { 00223 if (nelements == 0) return phSUCCESS; 00224 00225 /* We use the temp for an intermediate swap */ 00226 uint8_t *temp = (uint8_t *)malloc(sizeof(uint32_t)); 00227 00228 if (temp == NULL) return phFAIL; 00229 00230 if (method) 00231 { 00232 ph_quicksort_iterative( array, 00233 0, 00234 nelements-1, 00235 sizeof(uint32_t), 00236 temp, 00237 ph_qs_compare_uint32_t ); 00238 } 00239 else 00240 { 00241 ph_quicksort_recursive( array, 00242 0, 00243 nelements-1, 00244 sizeof(uint32_t), 00245 temp, 00246 ph_qs_compare_uint32_t ); 00247 } 00248 00249 phFree(temp); 00250 00251 return phSUCCESS; 00252 } 00253 00254 /* ---------------------------------------------------------------------- */ 00255 int32_t ph_qs_randomfill_uint32_t( const uint32_t nelements, 00256 uint32_t *array, 00257 const uint32_t maxval ) 00258 { 00259 uint32_t i = 0; 00260 00261 for ( i = 0; i < nelements; i++ ) 00262 array[i] = ((uint32_t)random()) % maxval; 00263 00264 return phSUCCESS; 00265 } 00266 00267 /* ---------------------------------------------------------------------- */ 00268 /* Print the uint32_t array */ 00269 int32_t ph_qs_print_uint32_t(const uint32_t nelements, 00270 const uint32_t *array ) 00271 { 00272 uint32_t i = 0; 00273 00274 printf("array[ "); 00275 00276 for ( i = 0; i < nelements; i++ ) 00277 printf("%4u%s",array[i],(i == (nelements-1)) ? " ];\n" : ", "); 00278 00279 return phSUCCESS; 00280 } 00281 00282 /* ---------------------------------------------------------------------- */ 00283 /* Verify the uint32_t array is sorted */ 00284 int32_t ph_qs_verify_uint32_t(const uint32_t nelements, 00285 const uint32_t *array ) 00286 { 00287 uint32_t i = 0; 00288 00289 for (i = 0; i < nelements - 1; i++ ) 00290 if (array[i] > array[i+1]) 00291 return phFAIL; 00292 00293 return phSUCCESS; 00294 } 00295 00296 #ifdef __cplusplus 00297 } 00298 #endif
Copyright (C) 2002 - 2007 |
Philip D.S. Thoren ( pthoren@users.sourceforge.net ) University Of Massachusetts at Lowell Robotics Lab |