Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

phQuicksort.cpp

Go to the documentation of this file.
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
SourceForge.net Logo

Generated on Sat Jun 16 02:44:02 2007 for phission by  doxygen 1.4.4