|
|
1.1 root 1:
2: /* Shellsort is a variation on Insertion Sort that is virtually unbeatable
3: * on small data sets. Insertion Sort is slow because it only exchanges
4: * adjacent elements. Shellsort circumvents this by allowing the exchange
5: * of elements that are farther apart. It works by first performing Insertion
6: * Sort on subsets of the data. For example, Shellsort might first sort
7: * the set of elements 1, 6, 11, 16... relative to each other--the effect
8: * is that the elements in that subset are moved much closer to their final
9: * positions. At first the sets are wide-spread, perhaps every fortieth
10: * element. Then it repeats using a tighter set, perhaps every fourteenth
11: * element, then every fourth element. Each of these passes is much cheaper
12: * than a traditional Insertion Sort pass. The effect of the passes is that
13: * the data set is mutated to be in "almost sorted" order. The final insertion
14: * sort pass can then go very quickly because insertion sort does very well on
15: * almost sorted data. In other words, at first the elements take large leaps
16: * to the general location they belong and successively smaller steps move the
17: * element to its precise place. I call this algorithm "inscrutable sort"
18: * because even after having coded the algorithm, I still have trouble
19: * following the animation. No one has been able to analyze this algorithm
20: * rigorously; the functional form of the running time is conjectured to be
21: * O(N^1.25). Shellsort may be a bit mysterious, but it is an good general
22: * purpose sort since it has excellent performance and the code you must write
23: * is only slightly more complex than Insertion Sort.
24: *
25: * Author: Julie Zelenski, NeXT Developer Support
26: * You may freely copy, distribute and reuse the code in this example.
27: * NeXT disclaims any warranty of any kind, expressed or implied, as to
28: * its fitness for any particular use.
29: */
30:
31:
32: #import "ShellSort.h"
33:
34:
35: @implementation ShellSort:GenericSort
36:
37:
38: - init;
39: {
40: [super init];
41: sortName = "Shellsort";
42: sortNum = SHELL_SORT;
43: return self;
44: }
45:
46: - sort;
47: /* Because Shellsort is a variation on Insertion Sort, it has the same
48: * inconsistency that I noted in the InsertionSort class. Notice where I
49: * subtract a move to compensate for calling a swap for visual purposes.
50: */
51: {
52: #define STRIDE_FACTOR 3 // good value for stride factor is not well-understood
53: // 3 is a fairly good choice (Sedgewick)
54: int c,d, stride;
55: BOOL found;
56:
57: [super sort];
58: fcalls++;
59: stride = 1;
60: while (stride <= numElements)
61: stride = stride*STRIDE_FACTOR +1;
62:
63: while (stride>(STRIDE_FACTOR-1)) { // loop to sort for each value of stride
64: stride = stride / STRIDE_FACTOR;
65: for (c = stride; c < numElements; c++){
66: found = NO;
67: d = c-stride;
68: while ((d >= 0) && !found) { // move to left until correct place
69: if ([self lessThan:d+stride :d]) {
70: [self swap:d+stride with:d];//swap each time(visual effect)
71: moves--; // subtract move to make fair
72: d -= stride; // jump by stride factor
73: } else
74: found = YES;
75: }
76: }
77: }
78: [self sortDone];
79: return self;
80: }
81:
82: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.