vecops.c
上传用户:lengbin
上传日期:2010-03-31
资源大小:121k
文件大小:15k
开发平台:

C/C++

  1. /*----------------------------------------------------------------------
  2.   File    : vecops.c
  3.   Contents: some special vector operations
  4.   Author  : Christian Borgelt
  5.   History : 16.09.1996 file created
  6.             04.02.1999 long int changed to int
  7.             03.06.2001 function v_shuffle added
  8.             02.01.2002 functions v_intsort, v_fltsort, v_dblsort added
  9.             03.03.2002 functions v_reverse, v_intrev etc. added
  10.             21.08.2003 function v_heapsort added
  11. ----------------------------------------------------------------------*/
  12. #include <assert.h>
  13. #include "vecops.h"
  14. /*----------------------------------------------------------------------
  15.   Preprocessor Definitions
  16. ----------------------------------------------------------------------*/
  17. #define TH_INSERT      16       /* threshold for insertion sort */
  18. #define BUFSIZE      4096       /* size of buffers for shifting */
  19. /*----------------------------------------------------------------------
  20.   Functions
  21. ----------------------------------------------------------------------*/
  22. static void _rec (void **vec, int n, VCMPFN cmpfn, void *data)
  23. {                               /* --- recursive part of sort */
  24.   void **l, **r;                /* pointers to exchange positions */
  25.   void *x,  *t;                 /* pivot element and exchange buffer */
  26.   int  m;                       /* number of elements in 2nd section */
  27.   do {                          /* sections sort loop */
  28.     l = vec; r = l +n -1;       /* start at left and right boundary */
  29.     if (cmpfn(*l, *r, data) > 0) {  /* bring the first and last */
  30.       t = *l; *l = *r; *r = t; }    /* element into proper order */
  31.     x = vec[n >> 1];            /* get the middle element as pivot */
  32.     if      (cmpfn(x, *l, data) < 0) x = *l;  /* try to find a */
  33.     else if (cmpfn(x, *r, data) > 0) x = *r;  /* better pivot */
  34.     while (1) {                 /* split and exchange loop */
  35.       while (cmpfn(*++l, x, data) < 0)    /* skip left  elements that */
  36.         ;                       /* are smaller than the pivot element */
  37.       while (cmpfn(*--r, x, data) > 0)    /* skip right elements that */
  38.         ;                       /* are greater than the pivot element */
  39.       if (l >= r) {             /* if less than two elements left, */
  40.         if (l <= r) { l++; r--; } break; }       /* abort the loop */
  41.       t = *l; *l = *r; *r = t;  /* otherwise exchange elements */
  42.     }
  43.     m = (int)(vec +n -l);       /* compute the number of elements */
  44.     n = (int)(r -vec +1);       /* right and left of the split */
  45.     if (n > m) {                /* if right section is smaller, */
  46.       if (m >= TH_INSERT)       /* but larger than the threshold, */
  47.         _rec(l, m, cmpfn, data); } /* sort it by a recursive call, */
  48.     else {                      /* if the left section is smaller, */
  49.       if (n >= TH_INSERT)       /* but larger than the threshold, */
  50.         _rec(vec, n, cmpfn, data); /* sort it by a recursive call, */
  51.       vec = l; n = m;           /* then switch to the right section */
  52.     }                           /* keeping its size m in variable n */
  53.   } while (n >= TH_INSERT);     /* while greater than threshold */
  54. }  /* _rec() */
  55. /*--------------------------------------------------------------------*/
  56. void v_sort (void *vec, int n, VCMPFN cmpfn, void *data)
  57. {                               /* --- quick sort for pointer vectors */
  58.   int  k;                       /* size of first section */
  59.   void **l, **r;                /* to traverse the vector */
  60.   void *t;                      /* exchange buffer */
  61.   assert(vec && (n >= 0) && cmpfn);   /* check the function arguments */
  62.   if (n <= 1) return;           /* do not sort less than two elements */
  63.   if (n < TH_INSERT)            /* if fewer elements than threshold */
  64.     k = n;                      /* for insertion sort, note the */
  65.   else {                        /* number of elements, otherwise */
  66.     _rec(vec, n, cmpfn, data);  /* call the recursive function */
  67.     k = TH_INSERT -1;           /* and get the number of elements */
  68.   }                             /* in the first vector section */
  69.   for (l = r = vec; --k > 0; )  /* find the smallest element within */
  70.     if (cmpfn(*++r, *l, data) < 0) l = r;   /* the first k elements */
  71.   r = vec;                      /* swap the smallest element */
  72.   t = *l; *l = *r; *r = t;      /* to front as a sentinel */
  73.   while (--n > 0) {             /* insertion sort loop */
  74.     t = *++r;                   /* note the element to insert */
  75.     for (l = r; cmpfn(*--l, t, data) > 0; ) /* shift right elements */
  76.       l[1] = *l;                /* that are greater than the one to */
  77.     l[1] = t;                   /* insert and store the element to */
  78.   }                             /* insert in the place thus found */
  79. }  /* v_sort() */
  80. /*--------------------------------------------------------------------*/
  81. static void _sift (void **vec, int l, int r, VCMPFN cmpfn, void *data)
  82. {                               /* --- let element sift down in heap */
  83.   void *t;                      /* buffer for element */
  84.   int  i;                       /* index of first successor in heap */
  85.   t = vec[l];                   /* note sift element */
  86.   i = l +l +1;                  /* compute index of first successor */
  87.   do {                          /* sift loop */
  88.     if ((i < r)                 /* if second successor is greater */
  89.     &&  (cmpfn(vec[i], vec[i+1], data) < 0))
  90.       i++;                      /* go to the second successor */
  91.     if (cmpfn(t, vec[i], data) >= 0) /* if the successor is greater */
  92.       break;                         /* than the sift element, */
  93.     vec[l] = vec[i];            /* let the successor ascend in heap */
  94.     l = i; i += i +1;           /* compute index of first successor */
  95.   } while (i <= r);             /* while still within heap */
  96.   vec[l] = t;                   /* store the sift element */
  97. }  /* _sift() */
  98. /*--------------------------------------------------------------------*/
  99. void v_heapsort (void *vec, int n, VCMPFN cmpfn, void *data)
  100. {                               /* --- heap sort for pointer vectors */
  101.   int  l, r;                    /* boundaries of heap section */
  102.   void *t, **v;                 /* exchange buffer, vector */
  103.   if (n <= 1) return;           /* do not sort less than two elements */
  104.   l = n >> 1;                   /* at start, only the second half */
  105.   r = n -1;                     /* of the vector has heap structure */
  106.   while (--l >= 0)              /* while the heap is not complete, */
  107.     _sift(vec, l, r, cmpfn, data);     /* extend it by one element */
  108.   v = vec;                      /* type the vector pointer */
  109.   while (1) {                   /* heap reduction loop */
  110.     t = v[0]; v[0] = v[r];      /* swap the greatest element */
  111.     v[r] = t;                   /* to the end of the vector */
  112.     if (--r <= 0) break;        /* if the heap is empty, abort */
  113.     _sift(v, 0, r, cmpfn, data);
  114.   }                             /* let the element that has been */
  115. }  /* v_heapsort() */           /* swapped to front sift down */
  116. /*--------------------------------------------------------------------*/
  117. void v_move (void *vec, int off, int n, int pos, int esz)
  118. {                               /* --- move a vector section */
  119.   int i;                        /* loop variable */
  120.   int mid, end;                 /* middle and end index */
  121.   int *src, *dst;               /* to traverse vector */
  122.   int buf[BUFSIZE];             /* buffer for vector elements */
  123.   assert(vec                    /* check the function arguments */
  124.      && (off >= 0) && (n >= 0) && (pos >= 0) && (esz >= 0));
  125.   esz /= (int)sizeof(int);      /* adapt size, offsets, and counter */
  126.   pos *= esz; off *= esz; n *= esz;
  127.   end  = off +n;                /* normalize vector indices */
  128.   if (pos <= off) { mid = off; off = pos; }
  129.   else            { mid = end; end = pos; }
  130.   if (mid -off < end -mid) {    /* if first section is smaller */
  131.     while (mid > off) {         /* while there are elements to shift */
  132.       n   = (mid -off < BUFSIZE) ? mid -off : BUFSIZE;
  133.       src = (int*)vec +mid -n;  /* get number of elements and */
  134.       dst = buf;                /* copy source to the buffer */
  135.       for (i = n;        --i >= 0; ) *dst++ = *src++;
  136.       dst = (int*)vec +mid -n;  /* shift down/left second section */
  137.       for (i = end -mid; --i >= 0; ) *dst++ = *src++;
  138.       src = buf;                /* copy buffer to destination */
  139.       for (i = n;        --i >= 0; ) *dst++ = *src++;
  140.       mid -= n; end -= n;       /* second section has been shifted */
  141.     } }                         /* down/left cnt elements */
  142.   else {                        /* if second section is smaller */
  143.     while (end > mid) {         /* while there are elements to shift */
  144.       n   = (end -mid < BUFSIZE) ? end -mid : BUFSIZE;
  145.       src = (int*)vec +mid +n;  /* get number of elements and */
  146.       dst = buf +n;             /* copy source to the buffer */
  147.       for (i = n;        --i >= 0; ) *--dst = *--src;
  148.       dst = (int*)vec +mid +n;  /* shift up/right first section */
  149.       for (i = mid -off; --i >= 0; ) *--dst = *--src;
  150.       src = buf +n;             /* copy buffer to destination */
  151.       for (i = n;        --i >= 0; ) *--dst = *--src;
  152.       mid += n; off += n;       /* first section has been shifted */
  153.     }                           /* up/right cnt elements */
  154.   }
  155. }  /* v_move() */
  156. /*--------------------------------------------------------------------*/
  157. void v_shuffle (void *vec, int n, double randfn (void))
  158. {                               /* --- shuffle vector entries */
  159.   int  i;                       /* vector index */
  160.   void **v = vec, *t;           /* vector and exchange buffer */
  161.   while (--n > 0) {             /* shuffle loop (n random selections) */
  162.     i = (int)((n+1) *randfn()); /* compute a random index */
  163.     if (i > n) i = n;           /* in the remaining section and */
  164.     if (i < 0) i = 0;           /* exchange the vector elements */
  165.     t = v[i]; v[i] = v[n]; v[n] = t;
  166.   }
  167. }  /* v_shuffle() */
  168. /*--------------------------------------------------------------------*/
  169. void v_reverse (void *vec, int n)
  170. {                               /* --- reverse a pointer vector */
  171.   void **v, *t;                 /* vector and exchange buffer */
  172.   for (v = vec; --n > 0; ) {    /* reverse the order of the elements */
  173.     t = v[n]; v[n] = v[0]; *v++ = t; }
  174. }  /* v_reverse() */
  175. /*--------------------------------------------------------------------*/
  176. #define REC(type,rec) 
  177. static void rec (type *vec, int n) 
  178. {                               /* --- recursive part of sort */       
  179.   type *l, *r;                  /* pointers to exchange positions */   
  180.   type x, t;                    /* pivot element and exchange buffer */
  181.   int  m;                       /* number of elements in sections */   
  182.                                                                        
  183.   do {                          /* sections sort loop */               
  184.     l = vec; r = l +n -1;       /* start at left and right boundary */ 
  185.     if (*l > *r) { t = *l; *l = *r; *r = t; }                          
  186.     x = vec[n >> 1];            /* get the middle element as pivot */  
  187.     if      (x < *l) x = *l;    /* compute median of three */          
  188.     else if (x > *r) x = *r;    /* to find a better pivot */           
  189.     while (1) {                 /* split and exchange loop */          
  190.       while (*++l < x)          /* skip left  elements that are */     
  191.         ;                       /* smaller than the pivot element */   
  192.       while (*--r > x)          /* skip right elements that are */     
  193.         ;                       /* greater than the pivot element */   
  194.       if (l >= r) {             /* if less than two elements left, */  
  195.         if (l <= r) { l++; r--; } break; }       /* abort the loop */  
  196.       t = *l; *l = *r; *r = t;  /* otherwise exchange elements */      
  197.     }                                                                  
  198.     m = (int)(vec +n -l);       /* compute the number of elements */   
  199.     n = (int)(r -vec +1);       /* right and left of the split */      
  200.     if (n > m) {                /* if right section is smaller, */     
  201.       if (m >= TH_INSERT)       /* but larger than the threshold, */   
  202.         rec(l, m); }            /* sort it by an recursive call */     
  203.     else {                      /* if the left section is smaller, */  
  204.       if (n >= TH_INSERT)       /* but larger than the threshold, */   
  205.         rec(vec, n);            /* sort it by an recursive call, */    
  206.       vec = l; n = m;           /* then switch to the right section */ 
  207.     }                           /* keeping its size m in variable n */ 
  208.   } while (n >= TH_INSERT);     /* while greater than threshold */     
  209. }  /* rec() */
  210. /*--------------------------------------------------------------------*/
  211. #define SORT(type,rec,sort) 
  212. void sort (type *vec, int n) 
  213. {                               /* --- sort a number vector */         
  214.   int  k;                       /* size of first section */            
  215.   type *l, *r;                  /* to traverse the vector */           
  216.   type t;                       /* exchange buffer */                  
  217.                                                                        
  218.   assert(vec && (n >= 0));      /* check the function arguments */     
  219.   if (n <= 1) return;           /* do not sort less than two elems. */ 
  220.   if (n < TH_INSERT)            /* if less elements than threshold */  
  221.     k = n;                      /* for insertion sort, note the */     
  222.   else {                        /* number of elements, otherwise */    
  223.     rec(vec, n);                /* call the recursive sort function */ 
  224.     k = TH_INSERT -1;           /* and get the number of elements */   
  225.   }                             /* in the first vector section */      
  226.   for (l = r = vec; --k > 0; )  /* find position of smallest element */
  227.     if (*++r < *l) l = r;       /* within the first k elements */      
  228.   r = vec;                      /* swap the smallest element */        
  229.   t = *l; *l = *r; *r = t;      /* to front as a sentinel */           
  230.   while (--n > 0) {             /* standard insertion sort */          
  231.     t = *++r;                   /* note the number to insert */        
  232.     for (l = r; *--l > t; k--)  /* shift right all numbers that are */ 
  233.       l[1] = *l;                /* greater than the one to insert */   
  234.     l[1] = t;                   /* and store the number to insert */   
  235.   }                             /* in the place thus found */          
  236. }  /* sort() */
  237. /*--------------------------------------------------------------------*/
  238. REC (int,    _intrec)
  239. SORT(int,    _intrec, v_intsort)
  240. /*--------------------------------------------------------------------*/
  241. REC (float,  _fltrec)
  242. SORT(float,  _fltrec, v_fltsort)
  243. /*--------------------------------------------------------------------*/
  244. REC (double, _dblrec)
  245. SORT(double, _dblrec, v_dblsort)
  246. /*--------------------------------------------------------------------*/
  247. #define REVERSE(type,reverse) 
  248. void reverse (type *vec, int n) 
  249. {                               /* --- reverse a number vector */      
  250.   type t;                       /* exchange buffer */                  
  251.   while (--n > 0) {             /* reverse the order of the elems. */  
  252.     t = vec[n]; vec[n] = vec[0]; *vec++ = t; }                         
  253. }  /* reverse() */
  254. /*--------------------------------------------------------------------*/
  255. REVERSE(int,    v_intrev)
  256. REVERSE(float,  v_fltrev)
  257. REVERSE(double, v_dblrev)