File: hsort.c

package info (click to toggle)
cucipop 1.31-13
  • links: PTS
  • area: non-free
  • in suites: potato
  • size: 292 kB
  • ctags: 394
  • sloc: ansic: 2,380; sh: 157; makefile: 103
file content (54 lines) | stat: -rw-r--r-- 2,052 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
/************************************************************************
 *	A heap sort implementation					*
 *									*
 *	Copyright (c) 1994-1997, S.R. van den Berg, The Netherlands	*
 *	#include "../README"						*
 ************************************************************************/
#ifdef RCS
static /*const*/char rcsid[]=
 "$Id: hsort.c,v 1.3 1998/05/11 14:26:40 srb Exp $";
#endif

#include <sys/types.h>

#include "hsort.h"

typedef unsigned char*bytep;

#define fpcmp(p1,p2)	((*fcmp)(p1,p2))
#define swap(p1,p2)	((*fswap)(p1,p2))
				/* heapsort, drop-in replacement for qsort() */
void hsort(base,nelem,width,fcmp,fswap)void*base;size_t nelem,width;
 register int(*fcmp)P((const void*,const void*));
 register void(*fswap)P((const void*,const void*));
{ register bytep rroot,root;register size_t leafoffset;
  if((leafoffset=nelem)<2)		      /* we won't do it for less :-) */
     return;		       /* actually, we only *need* to check for zero */
  for(root=(rroot=base)+width*(leafoffset>>1),
   leafoffset=width*(leafoffset-1);;)
   { if(root>rroot)				      /* tree still growing? */
	root-=width;			      /* gradually build up the tree */
     else
      { swap(root,root+leafoffset);	      /* move the highest into place */
	if(!(leafoffset-=width))			  /* shrink the tree */
	   return;						   /* ready! */
      }
     ;{ register bytep parent;
	for(parent=root;;)		/* sift the root element to its spot */
	 { register bytep child;size_t childoffset;
	   child=rroot+(childoffset=(parent-rroot<<1)+width);  /* find child */
	   if(childoffset<leafoffset)		     /* child within bounds? */
	    { if(fpcmp(child,child+width)<0)	     /* pick highest sibling */
		 child+=width;
docmp:	      if(fpcmp(parent,child)<0)		 /* parent lower than child? */
	       { swap(parent,child);parent=child;
		 continue;
	       }					    /* delve deeper! */
	    }
	   else if(childoffset==leafoffset)		      /* no sibling? */
	      goto docmp;		    /* then compare it with this one */
	   break;					  /* it settled down */
	 }
      }
   }
}