fastsort.c
上传用户:alex082
上传日期:2007-01-08
资源大小:2k
文件大小:4k
开发平台:

C/C++

  1. /*
  2. *
  3. * fastsort - sort a file in place - fast!
  4. *
  5. * Written 03/01/89 by Edwin R. Carp
  6. *
  7. * Copyright 1989 by Edwin R. Carp
  8. *
  9. *
  10. * John F. Haugh II, modified 3/3/89
  11. *
  12. * Completely rehacked to remove the two pass garbage
  13. * and quit pushing strings about in memory.  Reads
  14. * entire file in with one call, splits into lines and
  15. * saves pointers to each.  Then sorts pointers and
  16. * outputs lines.
  17. *
  18. * No big deal ...
  19. *
  20. *
  21. * Terence M. Donahue, modified 3/4/89
  22. *
  23. * Uses fputs() instead of fprintf() to output the sorted lines
  24. * Inlined the string compare into the compare() function.
  25. *
  26. * It is now about as fast as sort on my machine...
  27. *
  28. * There is a slow homemade quicksort routine #ifdef'ed out.
  29. * Once it is fast enough, compile -DHOMEMADE to have it replace qsort
  30. */
  31. #include <stdio.h>
  32. #include <sys/types.h>
  33. #include <sys/stat.h>
  34. #include <fcntl.h>
  35. nomem (s)
  36. char *s;
  37. {
  38. fprintf (stderr, "Can't get memory for %sn", s);
  39. exit (1);
  40. }
  41. #ifdef HOMEMADE
  42. /*
  43. ** This homemade quicksort is currently much slower than qsort,
  44. ** especially for large arrays.
  45. **
  46. ** Future improvements:
  47. **
  48. **    inline the strcmps
  49. **    do the recursive sort call on the smaller partition
  50. **    switch to an insertion sort on partitions smaller than 8 elements
  51. */
  52. #define exch(x,y) (temp = x, x = y, y = temp)
  53. void sort(v,left,right)
  54.      char *v[];
  55.      int left,right;
  56. {
  57.   int i, last;
  58.   char *temp;
  59.   while (left < right) {
  60.     /* Determine pivot by taking the median of left, middle, and right */
  61.     i = (left+right)>>1;
  62.     if (strcmp(v[left],v[right]) > 0) {
  63.       if (strcmp(v[left],v[i]) < 0)       i = left;
  64.       else if (strcmp(v[right],v[i]) > 0) i = right;
  65.     }
  66.     else {
  67.       if (strcmp(v[left],v[i]) > 0)       i = left;
  68.       else if (strcmp(v[right],v[i]) < 0) i = right;
  69.     }
  70.     exch(v[left],v[i]);
  71.     last = left;
  72.     for (i=left+1; i <= right; i++)
  73.       if (strcmp(v[i],v[left]) < 0)
  74. if (i != ++last) { exch(v[last],v[i]); }
  75.     exch(v[left],v[last]);
  76.     if (left < last-1) sort(v, left, last-1);
  77.     left = last+1;
  78.   }
  79. }
  80. #else
  81. compare(sp1,sp2)
  82.      char **sp1,**sp2;
  83. {
  84.   char *s1,*s2;
  85.   s1 = *sp1; s2 = *sp2;
  86.   while(*s1 == *s2++)
  87.     if(*s1++ == '') return 0;
  88.   return(*s1 - *--s2);
  89. }
  90. #endif
  91. main(argc, argv)
  92. int argc;
  93. char **argv;
  94. {
  95. int fd;
  96. char *malloc ();
  97. char *realloc ();
  98. char *cp;
  99. char *buf;
  100. char **lines;
  101. int cnt, cur, max;
  102. struct stat statbuf;
  103. FILE *fp;
  104. if (argc < 2) {
  105. fprintf (stderr, "usage: fastsort files ...n");
  106. exit (1);
  107. }
  108. while (*++argv) {
  109. if (stat (*argv, &statbuf)) {
  110. perror(*argv);
  111. continue;
  112. }
  113. if (! (buf = malloc ((unsigned) statbuf.st_size + 1)))
  114. nomem (*argv);
  115. if ((fd = open (*argv, O_RDONLY)) < 0) {
  116. perror (*argv);
  117. continue;
  118. }
  119. if (read (fd, buf, statbuf.st_size) != statbuf.st_size) {
  120. perror (*argv);
  121. free (buf);
  122. continue;
  123. }
  124. close (fd);
  125. *(cp = &buf[statbuf.st_size]) = '';
  126. cur = 0;
  127. max = 10;
  128. if (! (lines = (char **) malloc (sizeof (char *) * max)))
  129. nomem (*argv);
  130. while (--cp != buf) {
  131. if (*cp == 'n') {
  132. *cp = '';
  133. if (cur == max)
  134. if (! (lines = (char **) realloc (lines, sizeof (char *) * (max += 10))))
  135. nomem (*argv);
  136. lines[cur++] = cp + 1;
  137. }
  138. }
  139. lines[0] = buf; /* fix our earlier mistake :-) */
  140. #ifdef HOMEMADE
  141. sort (lines, 0, cur-1);
  142. #else
  143. qsort ((char *) lines, cur, sizeof (char *), compare);
  144. #endif
  145. if (! (fp = fopen (*argv, "w"))) {
  146. perror (*argv);
  147. continue;
  148. }
  149. for (max = cur, cur = 0;cur < max;cur++) {
  150. fputs (lines[cur], fp);
  151. putc ('n', fp);
  152. }
  153. fflush (fp);
  154. fclose (fp);
  155. free (lines);
  156. free (buf);
  157. }
  158. exit (0);
  159. }