typedef struct stackitem_S { uint32_t index; struct stackitem_S* next; } stackitem_T; #define PUSH(i) \ { \ if (stack_items == '\0') \ { \ if ( (stack_new = (stackitem_T*)malloc(sizeof(stackitem_T))) == '\0') \ { \ while (stack_items != '\0') \ { \ stack_next = stack_items->next; \ free(stack_items); \ stack_items = stack_next; \ } \ \ return -1; \ } \ } \ else \ { \ stack_new = stack_items; \ stack_items = stack_items->next; \ } \ \ stack_new->index = i; \ stack_new->next = stack; \ stack = stack_new; \ } #define POP(i) \ { \ stack_item = stack; \ *(i) = stack_item->index; \ stack = stack->next; \ stack_item->next = stack_items; \ stack_items = stack_item; \ } /* Non-recursing imlementation of quicksort. Subfiles are stored * on a heap-based stack, so instead of running out of stack space it * is possible to run out of memory for some inputs. * * items is a pointer to an array on user-defined objects * count is the number of items * lt is a pointer to a function that returns 1 (true) if items[i1] * is less then items[i2], 0 (false) otherwise. * swap is a pointer to a function that swaps the values items[l] and items[r]. * * The function returns 0 on success, -1 if there was a memory * allocation failure. */ int qsort(void* items, uint32_t count, int (*lt)(void* items, uint32_t i1, uint32_t i2), void (*swap)(void* items, uint32_t l, uint32_t r)) { stackitem_T* stack_items = '\0'; stackitem_T* stack = '\0'; stackitem_T* stack_next; stackitem_T* stack_new; stackitem_T* stack_item; uint32_t l; uint32_t r; uint32_t i; uint32_t j; uint32_t lps; /* left partition size */ uint32_t rps; /* right partition size */ if (count <= 1) return 0; PUSH(count - 1); PUSH(0); while (stack != '\0') { POP(&l); POP(&r); for (;;) { /* Begin partition step. */ /* Median of three partitioning. */ if ((r - l + 1) >= 4) { swap(items, (l + r) >> 1, r - 1); if (lt(items, r - 1, l)) swap(items, l, r - 1); if (lt(items, r, l)) swap(items, l, r); if (lt(items, r, r - 1)) swap(items, r - 1, r); i = l + 1; j = r; } else { i = l; j = r; } /* Main partition loop. */ for (;;) { while (lt(items, i, r)) ++i; while (lt(items, r, --j)) { if (j == l) break; } if (i >= j) break; swap(items, i, j); } swap(items, i, r); /* End partition step. */ lps = i - l; rps = r - i; if (lps > rps) { if (lps > 1) { if (rps > 1) { /* push left partition */ PUSH(i - 1); PUSH(l); /* set right partition manually */ l = i + 1; /* r is already set */ } else { /* set left partition manually */ /* l is already set */ r = i - 1; } } else break; } else { if (rps > 1) { if (lps > 1) { /* push right partition */ PUSH(r); PUSH(i + 1); /* set left partition manually */ r = i - 1; /* l is already set */ } else { /* set right partition manually */ /* r is already set */ l = i + 1; } } else break; } } } /* Free the heap based stack items. */ while (stack_items != '\0') { stack_next = stack_items->next; free(stack_items); stack_items = stack_next; } return 0; } /* static int lt(void* items, uint32_t i1, uint32_t i2) { uint32_t* numbers = (uint32_t*)items; if (numbers[i1] < numbers[i2]) return 1; else return 0; } static void swap(void* items, uint32_t l, uint32_t r) { uint32_t* numbers = (uint32_t*)items; uint32_t temp = numbers[l]; numbers[l] = numbers[r]; numbers[r] = temp; } */