diff --git a/qsort.h b/qsort.h index 6f7f078..4f25b75 100644 --- a/qsort.h +++ b/qsort.h @@ -1,7 +1,6 @@ #ifndef _QSORT_H #define _QSORT_H -//general quicksort suitable if we do not want to create extra class for the member type but prefer to encapsulate it into compare and swap soutines -//returns parity of the permutation +//quicksort, returns parity of the permutation template int genqsort(INDEX l, INDEX r,COMPAR (*cmp)(const INDEX, const INDEX), void (*swap)(const INDEX,const INDEX)) @@ -12,7 +11,7 @@ int parity=0; if(r<=l) return parity; //1 element if(cmp(r,l)<0) {parity^=1; swap(l,r);} if(r-l==1) return parity; //2 elements and preparation for median -piv= (l+r)/2; //pivoting by median of 3 - safer +piv= l+(r-l)/2; //pivoting by median of 3 - safer if(cmp(piv,l)<0) {parity^=1; swap(l,piv);} //and change the pivot element implicitly if(cmp(r,piv)<0) {parity^=1; swap(r,piv);} //and change the pivot element implicitly if(r-l==2) return parity; //in the case of 3 elements we are finished too @@ -43,19 +42,21 @@ return parity; } + //for SORTABLE classes which provide LA_sort_traits::compare and swap member functions -template -int memqsort(SORTABLE &object, INDEX l, INDEX r) +//this allows to use it in general templates also for complex elements, for which comparison falls back to error +template +int memqsort(SORTABLE &object, PERMINDEX *perm, INDEX l, INDEX r) { INDEX i,j,piv; int parity=0; if(r<=l) return parity; //1 element -if(LA_sort_traits::compare(object,l,r)) {parity^=1; object.swap(l,r);} +if(LA_sort_traits::compare(object,l,r)) {parity^=1; object.swap(l,r); if(perm) {PERMINDEX tmp=perm[l]; perm[l]=perm[r]; perm[r]=tmp;}} if(r-l==1) return parity; //2 elements and preparation for median -piv= (l+r)/2; //pivoting by median of 3 - safer -if(LA_sort_traits::compare(object,l,piv)) {parity^=1; object.swap(l,piv);} //and change the pivot element implicitly -if(LA_sort_traits::compare(object,piv,r)) {parity^=1; object.swap(r,piv);} //and change the pivot element implicitly +piv= l+(r-l)/2; //pivoting by median of 3 - safer +if(LA_sort_traits::compare(object,l,piv)) {parity^=1; object.swap(l,piv); if(perm) {PERMINDEX tmp=perm[l]; perm[l]=perm[piv]; perm[piv]=tmp;}} //and change the pivot element implicitly +if(LA_sort_traits::compare(object,piv,r)) {parity^=1; object.swap(r,piv); if(perm) {PERMINDEX tmp=perm[r]; perm[r]=perm[piv]; perm[piv]=tmp;}} //and change the pivot element implicitly if(r-l==2) return parity; //in the case of 3 elements we are finished too //general case , l-th r-th already processed @@ -70,16 +71,96 @@ do{ if(i(object,l,j); if(i(object,i,r);} + {if(l(object,perm,l,j); if(i(object,perm,i,r);} else - {if(i(object,i,r); if(l(object,l,j);} + {if(i(object,perm,i,r); if(l(object,perm,l,j);} +return parity; +} + + +template +int ptrqsortup(S *l, S *r, PERMINDEX *perm=NULL) +{ +S *i,*j,*piv; +int parity=0; + +if(r-l<=0) return parity; //1 element +if(*l > *r) {parity^=1; {S tmp; tmp=*l; *l= *r; *r=tmp;} if(perm) {PERMINDEX tmp=*perm; *perm=perm[r-l]; perm[r-l]=tmp;}} +if(r-l==1) return parity; //2 elements and preparation for median +piv= l+(r-l)/2; //pivoting by median of 3 - safer +if(*l>*piv) {parity^=1; {S tmp; tmp=*l; *l=*piv; *piv=tmp;} if(perm) {PERMINDEX tmp= *perm; *perm=perm[piv-l]; perm[piv-l]=tmp;}} //and change the pivot element implicitly +if(*piv>*r) {parity^=1; {S tmp; tmp=*r; *r=*piv; *piv=tmp;} if(perm) {PERMINDEX tmp=perm[r-l]; perm[r-l]=perm[piv-l]; perm[piv-l]=tmp;}} //and change the pivot element implicitly +if(r-l==2) return parity; //in the case of 3 elements we are finished too + +//general case , l-th r-th already processed +i=l+1; j=r-1; +do{ + //important sharp inequality - stops at sentinel element for efficiency + // this is inefficient if all keys are equal - unnecessary n log n swaps are done, but we assume that it is atypical input + while(*piv > *i++); + i--; + while(*j-- > *piv); + j++; + if(i +int ptrqsortdown(S *l, S *r, PERMINDEX *perm=NULL) +{ +S *i,*j,*piv; +int parity=0; + +if(r-l<=0) return parity; //1 element +if(*l < *r) {parity^=1; {S tmp; tmp=*l; *l= *r; *r=tmp;} if(perm) {PERMINDEX tmp=*perm; *perm=perm[r-l]; perm[r-l]=tmp;}} +if(r-l==1) return parity; //2 elements and preparation for median +piv= l+(r-l)/2; //pivoting by median of 3 - safer +if(*l<*piv) {parity^=1; {S tmp; tmp=*l; *l=*piv; *piv=tmp;} if(perm) {PERMINDEX tmp= *perm; *perm=perm[piv-l]; perm[piv-l]=tmp;}} //and change the pivot element implicitly +if(*piv<*r) {parity^=1; {S tmp; tmp=*r; *r=*piv; *piv=tmp;} if(perm) {PERMINDEX tmp=perm[r-l]; perm[r-l]=perm[piv-l]; perm[piv-l]=tmp;}} //and change the pivot element implicitly +if(r-l==2) return parity; //in the case of 3 elements we are finished too + +//general case , l-th r-th already processed +i=l+1; j=r-1; +do{ + //important sharp inequality - stops at sentinel element for efficiency + // this is inefficient if all keys are equal - unnecessary n log n swaps are done, but we assume that it is atypical input + while(*piv < *i++); + i--; + while(*j-- < *piv); + j++; + if(i u(10); +for(int i=0; i<10;++i) u[i]=i; +ptrqsortup(&t[0],&t[9],&u[0]); +cout<