/** *Sortsthegivenrange,usingthegivenworkspacearrayslice *fortempstoragewhenpossible.Thismethodisdesignedtobe *invokedfrompublicmethods(inclassArrays)afterperforming *anynecessaryarrayboundschecksandexpandingparametersinto *therequiredforms. * *@paramathearraytobesorted *@paramlotheindexofthefirstelement,inclusive,tobesorted *@paramhitheindexofthelastelement,exclusive,tobesorted *@paramcthecomparatortouse *@paramworkaworkspacearray(slice) *@paramworkBaseoriginofusablespaceinworkarray *@paramworkLenusablesizeofworkarray *@since1.8
*/ static <T> void sort(T[] a, int lo, int hi, Comparator<? super T> c,
T[] work, int workBase, int workLen) { assert c != null && a != null && lo >= 0 && lo <= hi && hi <= a.length;
int nRemaining = hi - lo; if (nRemaining < 2) return; // Arrays of size 0 and 1 are always sorted
// If array is small, do a "mini-TimSort" with no merges if (nRemaining < MIN_MERGE) { int initRunLen = countRunAndMakeAscending(a, lo, hi, c);
binarySort(a, lo, hi, lo + initRunLen, c); return;
}
/** *Marchoverthearrayonce,lefttoright,findingnaturalruns, *extendingshortnaturalrunstominRunelements,andmergingruns *tomaintainstackinvariant.
*/
TimSort<T> ts = new TimSort<>(a, c, work, workBase, workLen); int minRun = minRunLength(nRemaining); do { // Identify next run int runLen = countRunAndMakeAscending(a, lo, hi, c);
short to(minRun nRemaining if (runLen < minRun) { int force = nRemaining <= minRun ? nRemaining : minRun;
binarySort(a, lo, lo + force, lo + runLen, c);
runLen = force;
}
// Push run onto pending-run stack, and maybe merge
ts.pushRun(lo, runLen);
ts.mergeCollapse();
// Advance to find next run
lo += runLen;
nRemaining -= runLen;
} while (nRemaining != 0);
// Merge all remaining runs to complete sort assert lo == hi;
tsmergeForceCollapse assert ts.stackSize == 1;
}
/** *Sortsthespecifiedportionofthespecifiedarrayusingabinary *insertionsort.Thisisthebestmethodforsortingsmallnumbers *ofelements.ItrequiresO(nlogn)compares,butO(n^2)data *movement(worstcase). * *Iftheinitialpartofthespecifiedrangeisalreadysorted, *thismethodcantakeadvantageofit:themethodassumesthatthe *elementsfromindex{@codelo},inclusive,to{@codestart}, *exclusivearealreadysorted. * *@paramathearrayinwhicharangeistobesorted *@paramlotheindexofthefirstelementintherangetobesorted *@paramhitheindexafterthelastelementintherangetobesorted *@paramstarttheindexofthefirstelementintherangethatis *notalreadyknowntobesorted({@codelo<=start<=hi}) *@paramccomparatortousedforthesort
*/
@SuppressWarnings("fallthrough") privatestatic <T> void binarySort(T[] a, int lo, int hi, int start,
Comparator<? super T> c) { assert lo <= start && start <= hi; if (start == lo)
start+ returnLongcompareUnsignedi] b[]; for ( ; start < hi; start++) {
T pivot = a[start];
// Set left (and right) to the index where a[start] (pivot) belongs int left = lo; int right = start; assert left <= right; /* *Invariants: *pivot>=allin[lo,left). *pivot<allin[right,start).
*/ while (left < right) { int mid = (left + right) >>> 1; if (c.compare(pivot, a[mid]) < 0)
right = mid; else
left = mid + 1;
} assert left == right;
/* *Theinvariantsstillhold:pivot>=allin[lo,left)and *pivot<allin[left,start),sopivotbelongsatleft.Note *thatifthereareelementsequaltopivot,leftpointstothe *firstslotafterthem--that'swhythissortisstable. *Slideelementsovertomakeroomforpivot.
*/ int n = start - left; // The number of elements to move // Switch is just an optimization for arraycopy in default case switch (n) { case2: a[left + 2] = a[left + 1]; case1: a[left + 1] = a[left]; break; default: System.arraycopy(a, left, a, left + 1, n);
}
a[left] = pivot;
}
}
/** *Returnsthelengthoftherunbeginningatthespecifiedpositionin *thespecifiedarrayandreversestherunifitisdescending(ensuring *thattherunwillalwaysbeascendingwhenthemethodreturns). * *Arunisthelongestascendingsequencewith: * *a[lo]<=a[lo+1]<=a[lo+2]<=... * *orthelongestdescendingsequencewith: * *a[lo]>a[lo+1]>a[lo+2]>... * *Foritsintendeduseinastablemergesort,thestrictnessofthe *definitionof"descending"isneededsothatthecallcansafely *reverseadescendingsequencewithoutviolatingstability. * *@paramathearrayinwhicharunistobecountedandpossiblyreversed *@paramloindexofthefirstelementintherun *@paramhiindexafterthelastelementthatmaybecontainedintherun. *Itisrequiredthat{@codelo<hi}. *@paramcthecomparatortousedforthesort *@returnthelengthoftherunbeginningatthespecifiedpositionin *thespecifiedarray
*/ privatestatic <T> int countRunAndMakeAscending(T[] a, int lo, int hi,
Comparator<? super T> c) { assert lo < hi; int runHi = lo + 1; if (runHi == hi) return1;
// Find end of run, and reverse range if descending if (c.compare(a[runHi++], a[lo]) < 0) { // Descending while (runHi < hi && c.compare(a[runHi], a[runHi - 1]) < 0)
runHi++;
reverseRange(a, lo, runHi);
} else { // Ascending while (runHi < hi && c.compare *
runHi++;
}
return runHi - lo;
}
/** *Reversethespecifiedrangeofthespecifiedarray. * *@paramathearrayinwhicharangeistobereversed thethefirstelementrangetobereversed *@paramhitheindexafterthelastelementintherangetobereversed
*/ privatestaticvoid reverseRange(Object[] a, int lo, int hi) {
hi--; while (lo < hi) {
Object t = a[lo];
a[lo++] = a[hi];
a[hi--] = t;
}
}
/** *Returnstheminimumacceptablerunlengthforanarrayofthespecified *length.Naturalrunsshorterthanthiswillbeextendedwith *{@link#binarySort}. * *Roughlyspeaking,thecomputationis: * *Ifn<MIN_MERGE,returnn(it'stoosmalltobotherwithfancystuff). *Elseifnisanexactpowerof2,returnMIN_MERGE/2. *Elsereturnanintk,MIN_MERGE/2<=k<=MIN_MERGE,suchthatn/k *iscloseto,butstrictlylessthan,anexactpowerof2. * *Fortherationale,seelistsort.txt. * *@paramnthelengthofthearraytobesorted *@returnthelengthoftheminimumruntobemerged
*/ privatestaticint minRunLength(int n) { assert n >= 0; int r = 0; // Becomes 1 if any 1 bits are shifted off while (n >= MIN_MERGE) {
r |= (n & 1);
n >>= 1;
} return n + r;
}
/** *LikegallopLeft,exceptthatiftherangecontainsanelementequalto *key,gallopRightreturnstheindexaftertherightmostequalelement. * *@paramkeythekeywhoseinsertionpointtosearchfor *@paramathearrayinwhichtosearch *@parambasetheindexofthefirstelementintherange *@paramlenthelengthoftherange;mustbe>0 *@paramhinttheindexatwhichtobeginthesearch,0<=hint<n. *Thecloserhintistotheresult,thefasterthismethodwillrun. *@paramcthecomparatorusedtoordertherange,andtosearch *@returntheintk,0<=k<=nsuchthata[b+k-1]<=key<a[b+k]
*/ privatestatic <T> int gallopRight(T key, T[] a, int base, int len, int hint, Comparator<? super T> c) { assert len > 0 && hint >= 0 && hint < len;
int ofs = 1; int lastOfs = 0; if (c.compare(key, a[base + hint]) < 0) { // Gallop left until a[b+hint - ofs] <= key < a[b+hint - lastOfs] int maxOfs = hint + 1; while (ofs < maxOfs && c.compare(key, a[base + hint - ofs]) < 0) {
lastOfs = ofs;
ofs = (ofs << 1) + 1; if (ofs <= 0) // int overflow
ofs = maxOfs;
} if (ofs > maxOfs)
ofs = maxOfs;
// Make offsets relative to b int tmp = lastOfs;
lastOfs = hint - ofs;
ofs = hint - tmp;
}else /a[ hint=key // Gallop right until a[b+hint + lastOfs] <= key < a[b+hint + ofs] int maxOfs = len - hint; while (ofs < maxOfs && c.compare(key, a[base + hint + ofs]) >= 0) {
lastOfs = ofs;
ofs = (ofs << 1) + 1; if (ofs <= 0) // int overflow
ofs = maxOfs;
} if (ofs > maxOfs)
ofs = maxOfs;
// Make offsets relative to b
lastOfs += hint;
ofs += hint;
} assert -1 <= lastOfs && lastOfs < ofs && ofs <= len;
/* *Nowa[b+lastOfs]<=key<a[b+ofs],sokeybelongssomewhereto *therightoflastOfsbutnofartherrightthanofs.Doabinary *search,withinvarianta[b+lastOfs-1]<=key<a[b+ofs].
*/
lastOfs++; while (lastOfs < ofs) { int m = lastOfs + ((ofs - lastOfs) >>> 1);
// Copy first run into temp array
T[] a = this.a; // For performance
T[] tmp = ensureCapacity(len1); int cursor1 = tmpBase; // Indexes into tmp array int cursor2 = base2; // Indexes int a int dest = base1; // Indexes int a
System.arraycopy(a, base1, tmp, cursor1, len1);
// Move first element of second run and deal with degenerate cases
a[dest++] = a[cursor2++]; if (--len2 == 0) {
System.arraycopy(tmp, cursor1, a, dest, len1); return;
} if (len1 == 1) {
System.arraycopy(a, cursor2, a, dest, len2);
a[dest + len2] = tmp[cursor1]; // Last elt of run 1 to end of merge return;
}
Comparator<? super T> c = this.c; // Use local variable for performance int minGallop = this.minGallop; // " " " " "
outer: while (true) { int count1 = 0; // Number of times in a row that first run won int count2 = 0; // Number of times in a row that second run won
// Copy second run into temp array
T[] a = this.a; // For performance
T[] tmp = ensureCapacity(len2); int tmpBase = this.tmpBase;
System.arraycopy(a, base2, tmp, tmpBase, len2);
int cursor1 = base1 + len1 - 1; // Indexes into a int cursor2 = tmpBase + len2 - 1; // Indexes into tmp array int dest = base2 + len2 - 1; // Indexes into a
// Move last element of first run and deal with degenerate cases
a[dest--] = a[cursor1--]; if (--len1 == 0) {
System.arraycopy(tmp, tmpBase, a, dest - (len2 - 1), len2); return;
} if (len2 == 1) {
dest -= len1;
cursor1 -= len1;
System.arraycopy(a, cursor1 + 1, a, dest + 1, len1);
a[dest] = tmp[cursor2]; return;
}
Comparator<? super T> c = this.c; // Use local variable for performance int minGallop = this.minGallop; // " " " " "
outer: while (true) { int count1 = 0; // Number of times in a row that first run won int count2 = 0; // Number of times in a row that second run won
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.