📄 sort.cc
字号:
#include <stdio.h>#include <ctype.h>#include <std.h>/* the next 6 #defines implement a very fast in-line stack abstraction */#define MAX_STACK_SIZE 32#define DISPOSE_STACK(S) (free(S))#define PUSH(LOW,HIGH) do {top->lo = LOW;top++->hi = HIGH;} while (0)#define POP(LOW,HIGH) do {LOW = (--top)->lo;HIGH = top->hi;} while (0)#define STACK_NOT_EMPTY (stack < top) #define SWAP(A,B) do {char *_temp = (A);(A) = (B);(B) = _temp;} while (0)/* Discontinue quicksort algorithm when partition gets below this size. This particular magic number was chosen to work best on a Sun 4/260. */#define MAX_THRESH 30/* Data structure for stack of unfulfilled obligations. */typedef struct { char **lo; char **hi;} stack_node;/* Once main array is partially sorted by quicksort the remainder is completely sorted using insertion sort, since this is efficient for partitions below MAX_THRESH size. BASE points to the beginning of the array to sort, and END_PTR points at the very last element in the array (*not* one beyond it!). */inline static voidinsert_sort (char **base_ptr, char **end_ptr){ char **run_ptr; char **tmp_ptr = base_ptr; char **thresh = end_ptr <? base_ptr + MAX_THRESH; /* Find the smallest element in the first threshold and put it at the end of the array. This is guaranteed to be the smallest element in the array, and it speeds up the inner loop of insertion sort. */ for (run_ptr = tmp_ptr + 1; run_ptr <= thresh; run_ptr++) if (strcmp (*run_ptr, *tmp_ptr) < 0) tmp_ptr = run_ptr; SWAP (*tmp_ptr, *base_ptr); /* Typical insertion sort, but we run from the `right-hand-side' downto the `left-hand-side.' */ for (run_ptr = base_ptr + 1; run_ptr < end_ptr; run_ptr++) { char *temp = *(tmp_ptr = run_ptr + 1); /* Select the correct location for the new element, by sliding everyone down by 1 to make room! */ while (strcmp (temp, *--tmp_ptr) < 0) tmp_ptr[1] = *tmp_ptr; tmp_ptr[1] = temp; }}/* Return the median value selected from among the LOW, MIDDLE, and HIGH. Rearrange LOW and HIGH so the three values are sorted amongst themselves. This speeds up later work... */inline static char *find_pivot (char **low, char **high){ char **middle = low + ((high - low ) >> 1); if (strcmp (*middle, *low) < 0) SWAP (*middle, *low); if (strcmp (*high, *middle) < 0) SWAP (*middle, *high); else return *middle; if (strcmp (*middle, *low) < 0) SWAP (*middle, *low); return *middle;}/* Order elements using quicksort. This implementation incorporates 4 optimizations discussed in Sedgewick: 1. Non-recursive, using an explicit stack of log (n) pointers that indicate the next array partition to sort. 2. Choses the pivot element to be the median-of-three, reducing the probability of selecting a bad pivot value. 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving insertion sort to sort within the partitions. This is a big win, since insertion sort is faster for small, mostly sorted array segements. 4. The larger of the 2 sub-partitions are always pushed onto the stack first, with the algorithm then concentrating on the smaller partition. This *guarantees* no more than log (n) stack size is needed! */ voidsort (char **base_ptr, int total_elems){ if (total_elems > MAX_THRESH) { char **lo = base_ptr; char **hi = lo + (total_elems - 1); char **left_ptr; char **right_ptr; stack_node stack[MAX_STACK_SIZE]; stack_node *top = stack + 1; while (STACK_NOT_EMPTY) { /* Select the median-of-three here. This allows us to skip forward for the LEFT_PTR and RIGHT_PTR. */ char *pivot = find_pivot (lo, hi); left_ptr = lo + 1; right_ptr = hi - 1; /* Here's the famous ``collapse the walls'' section of quicksort. Gotta like those tight inner loops! */ do { while (strcmp (*left_ptr, pivot) < 0) left_ptr++; while (strcmp (pivot, *right_ptr) < 0) right_ptr--; if (left_ptr < right_ptr) { SWAP (*left_ptr, *right_ptr); left_ptr++; right_ptr--; } else if (left_ptr == right_ptr) { left_ptr++; right_ptr--; break; } } while (left_ptr <= right_ptr); if ((right_ptr - lo) <= MAX_THRESH) { if ((hi - left_ptr) <= MAX_THRESH) /* ignore both small tables */ POP (lo, hi); else /* ignore small left table */ lo = left_ptr; } else if ((hi - left_ptr) <= MAX_THRESH) /* ignore small right table */ hi = right_ptr; else if ((right_ptr - lo) > (hi - left_ptr)) { /* push larger left table */ PUSH (lo, right_ptr); lo = left_ptr; } else { /* push larger right table */ PUSH (left_ptr, hi); hi = right_ptr; } } } insert_sort (base_ptr, base_ptr + (total_elems - 1));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -