⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qsort.c

📁 早期freebsd实现
💻 C
字号:
/* * qsort.c: * Our own version of the system qsort routine which is faster by an average * of 25%, with lows and highs of 10% and 50%. * The THRESHold below is the insertion sort threshold, and has been adjusted * for records of size 48 bytes. * The MTHREShold is where we stop finding a better median. */#define		THRESH		4		/* threshold for insertion */#define		MTHRESH		6		/* threshold for median */static  int		qsz;			/* size of each record */static  int		(*qcmp)();		/* the comparison routine */static  int		thresh;			/* THRESHold in chars */static  int		mthresh;		/* MTHRESHold in chars *//* * qsort: * First, set up some global parameters for qst to share.  Then, quicksort * with qst(), and then a cleanup insertion sort ourselves.  Sound simple? * It's not... */qsort (base, n, size, compar)     char *base;     int n;     int size;     int (*compar)();{  register char *i, *j, *lo, *hi, *min;  register int c;  char *max;  if (n <= 1)  return;  qsz = size;  qcmp = compar;  thresh = qsz*THRESH;  mthresh = qsz*MTHRESH;  max = base + n*qsz;  if (n >= THRESH)    {      qst (base, max);      hi = base + thresh;    }  else    {      hi = max;    }  /*   * First put smallest element, which must be in the first THRESH, in   * the first position as a sentinel.  This is done just by searching   * the first THRESH elements (or the first n if n < THRESH), finding   * the min, and swapping it into the first position.   */  for (j = lo = base; (lo += qsz) < hi; )    {      if ((*qcmp) (j, lo) > 0)	j = lo;    }  if (j != base)    {			/* swap j into place */      for (i = base, hi = base + qsz; i < hi;)	{	  c = *j;	  *j++ = *i;	  *i++ = c;	}    }  /*   * With our sentinel in place, we now run the following hyper-fast   * insertion sort.  For each remaining element, min, from [1] to [n-1],   * set hi to the index of the element AFTER which this one goes.   * Then, do the standard insertion sort shift on a character at a time   * basis for each element in the frob.   */  for (min = base; (hi = min += qsz) < max;)    {      while ( (*qcmp) (hi -= qsz, min) > 0);      if ((hi += qsz) != min)	{	  for (lo = min + qsz; --lo >= min;)	    {	      c = *lo;	      for (i = j = lo; (j -= qsz) >= hi; i = j)		*i = *j;	      *i = c;	    }	}    }}/* * qst: * Do a quicksort * First, find the median element, and put that one in the first place as the * discriminator.  (This "median" is just the median of the first, last and * middle elements).  (Using this median instead of the first element is a big * win).  Then, the usual partitioning/swapping, followed by moving the * discriminator into the right place.  Then, figure out the sizes of the two * partions, do the smaller one recursively and the larger one via a repeat of * this code.  Stopping when there are less than THRESH elements in a partition * and cleaning up with an insertion sort (in our caller) is a huge win. * All data swaps are done in-line, which is space-losing but time-saving. * (And there are only three places where this is done). */qst (base, max)     char *base, *max;{  register char *i, *j, *jj, *mid;  register int ii, c;  char *tmp;  int lo, hi;  lo = max - base;		/* number of elements as chars */  do    {      /*       * At the top here, lo is the number of characters of elements in the       * current partition.  (Which should be max - base).       * Find the median of the first, last, and middle element and make that the       * middle element.  Set j to largest of first and middle.  If max is larger       * than that guy, then it's that guy, else compare max with loser of first       * and take larger.  Things are set up to prefer the middle, then the first       * in case of ties.       */      mid = i = base + qsz * ((lo/qsz) >> 1);      if (lo >= mthresh)	{	  j = ((*qcmp) ((jj = base), i) > 0 ? jj : i);	  if ((*qcmp) (j, (tmp = max - qsz)) > 0)	    {	      j = (j == jj ? i : jj);	/* switch to first loser */	      if ((*qcmp) (j, tmp) < 0)		j = tmp;	    }	  if (j != i)	    {	      ii = qsz;	      do		{		  c = *i;		  *i++ = *j;		  *j++ = c;		}	      while(  --ii  );	    }	}      /*       * Semi-standard quicksort partitioning/swapping       */      for (i = base, j = max - qsz; ;)	{	  while (i < mid && (*qcmp) (i, mid) <= 0)	    i += qsz;	  while (j > mid)	    {	      if ((*qcmp) (mid, j) <= 0)		{		  j -= qsz;		  continue;		}	      tmp = i + qsz;		/* value of i after swap */	      if (i == mid)		{	/* j <-> mid, new mid is j */		  mid = jj = j;		}	      else		{			/* i <-> j */		  jj = j;		  j -= qsz;		}	      goto  swap;	    }	  if (i == mid)	    {	      break;	    }	  else	    {				/* i <-> mid, new mid is i */	      jj = mid;	      tmp = mid = i;		/* value of i after swap */	      j -= qsz;	    }	swap:	  ii = qsz;	  do	    {	      c = *i;	      *i++ = *jj;	      *jj++ = c;	    }	  while (--ii);	  i = tmp;	}      /*       * Look at sizes of the two partitions, do the smaller one first by       * recursion, then do the larger one by making sure lo is its size,       * base and max are update correctly, and branching back.       * But only repeat (recursively or by branching) if the partition is       * of at least size THRESH.       */      i = (j = mid) + qsz;      if ((lo = j - base) <= (hi = max - i))	{	  if (lo >= thresh)	    qst (base, j);	  base = i;	  lo = hi;	}      else	{	  if (hi >= thresh)	    qst (i, max);	  max = j;	}    }  while (lo >= thresh);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -