Skip to content

Repository files navigation

ChenSort

ChenSort is an improved bucket sort, which is a general-purpose sorting algorithm.

The time complexity is O(n) at best and O(nlogn) at worst, the space complexity is O(n), and it is stable.

Randomly generate [1000,10000000] random numbers in the range [-2^63,2^63-1], average speed is 3 times faster than Quicksort, fastest is 20 times. Traditional bucket sort cannot handle such a large range of values, because the performance is much worse than quicksort due to the huge resource consumption.

All performance data is performed under a single thread, which can easily support multi-threading.

Android APK demo, 6.05 MB

Windows exe demo, 5.8 MB

The demos are all built on Flutter.

Dart code:

/// The essence of Chen Sort is an improved bucket sortvoidchenSort(List<int> list) {
if (list.length <2) {
return;
}
int maxValue = list[0];
int minValue = maxValue;
for (final element in list.skip(1)) {
if (element > maxValue) {
maxValue = element;
}
if (element < minValue) {
minValue = element;
}
}
/// All elements are the same and do not need to be sorted.if (maxValue == minValue) {
return;
}
/// Limit the maximum size of the bucket to ensure the performance of long list /// sorting, which can be adjusted according to the actual situation. /// /// The essential difference between this and bucket sorting is that the size of /// the bucket is only related to the length of the list, not the range of element values.int bucketSize =min(list.length, 50000);
int maxBucketIndex = bucketSize -1;
List<List<int>?> buckets =List.filled(bucketSize, null);
int slot;
/// Calculate the bucket in which the element is located based on the value of the element /// and the maximum and minimum values./// Overflow detectionBigInt range =BigInt.from(maxValue) -BigInt.from(minValue);
if (BigInt.from(range.toInt()) == range) {
int range = maxValue - minValue;
double factor = maxBucketIndex / range;
for (final element in list) {
// slot = (((element - minValue) / range) * maxBucketIndex).toInt();
slot = ((element - minValue) * factor).toInt();
if (buckets[slot] ==null) {
buckets[slot] = [];
}
buckets[slot]!.add(element);
}
} else {
/// Overflowed(positive minus negative)int positiveRange = maxValue;
int negativeRange =-minValue;
int positiveStartBucketIndex = maxBucketIndex ~/2+1;
int positiveBucketLength = maxBucketIndex - positiveStartBucketIndex;
int negativeBucketLength = positiveStartBucketIndex -1;
for (final element in list) {
if (element <0) {
slot = negativeBucketLength -
((-element / negativeRange) * negativeBucketLength).toInt();
} else {
slot = positiveStartBucketIndex +
((element / positiveRange) * positiveBucketLength).toInt();
}
if (buckets[slot] ==null) {
buckets[slot] = [];
}
buckets[slot]!.add(element);
}
}
intcompare(int left, int right) {
return left - right;
}
int index =0;
for (final bucket in buckets) {
if (bucket !=null) {
if (bucket.length >1) {
if (bucket.length >=1000) {
chenSort(bucket);
} else {
/// The sort method here represents the fastest comparison-type algorithm (Quick sort, Tim sort, etc.) bucket.sort(compare);
}
for (final element in bucket) {
list[index++] = element;
}
} else {
list[index++] = bucket[0];
}
}
}
}

Java code(Multi-thread. The code just shows that this algorithm can easily support multi-threaded sorting, and the actual performance data is performed under a single thread):

staticvoidchenSort(Integer[] list) {
intlength = list.length;
if (length < 2) {
return;
}
IntegermaxValue = Integer.MIN_VALUE;
IntegerminValue = Integer.MAX_VALUE;
for (Integerelement : list) {
if (element > maxValue) {
maxValue = element;
}
if (element < minValue) {
minValue = element;
}
}
/// All elements are the same and do not need to be sorted.if (maxValue.equals(minValue)) {
return;
}
/// Limit the maximum size of the bucket to ensure the performance of long list/// sorting, which can be adjusted according to the actual situation.////// The essential difference between this and bucket sorting is that the size of/// the bucket is only related to the length of the list, not the range of element values.intbucketSize = Math.min(length, 50000);
intmaxBucketIndex = bucketSize - 1;
ArrayList<Integer>[] buckets = newArrayList[bucketSize];
intslot;
/// Calculate the bucket in which the element is located based on the value of the element/// and the maximum and minimum values./// Overflow detectionBigIntegerbigRange = BigInteger.valueOf(maxValue).subtract(BigInteger.valueOf(minValue));
if (BigInteger.valueOf(bigRange.intValue()).equals(bigRange)) {
doublefactor = maxBucketIndex * 1.0 / (maxValue - minValue);
for (Integerelement : list) {
slot = (int) ((element - minValue) * factor);
if (buckets[slot] == null) {
buckets[slot] = newArrayList<>();
}
buckets[slot].add(element);
}
} else {
/// Overflowed(positive minus negative)doublepositiveRange = maxValue;
doublenegativeRange = -minValue;
intpositiveStartBucketIndex = maxBucketIndex / 2 + 1;
intpositiveBucketLength = maxBucketIndex - positiveStartBucketIndex;
intnegativeBucketLength = positiveStartBucketIndex - 1;
Integerzero = 0;
for (Integerelement : list) {
if (element < zero) {
slot = negativeBucketLength - (int) ((-element / negativeRange) * negativeBucketLength);
} else {
slot = (int) (positiveStartBucketIndex + ((element / positiveRange) * positiveBucketLength));
}
if (buckets[slot] == null) {
buckets[slot] = newArrayList<>();
}
buckets[slot].add(element);
}
}
Comparator<Integer> comparator = Comparator.comparingInt(left -> left);
// Multi-thread sorting between bucketsCountDownLatchcountDownLatch = newCountDownLatch(buckets.length);
for (ArrayList<Integer> bucket : buckets) {
if (bucket != null) {
if (bucket.size() > 1) {
executor.execute(() -> {
bucket.sort(comparator);
countDownLatch.countDown();
});
} else {
countDownLatch.countDown();
}
} else {
countDownLatch.countDown();
}
}
try {
countDownLatch.await();
} catch (InterruptedExceptionignored) {
}
intindex = 0;
for (ArrayList<Integer> bucket : buckets) {
if (bucket != null) {
if (bucket.size() > 1) {
for (Integerelement : bucket) {
list[index++] = element;
}
} else {
list[index++] = bucket.get(0);
}
}
}
}

Performance(10 million random numbers sorted, single thread):

Randomrandom = newRandom();
Integer[] arr = newInteger[10000000];
longmaxValue = Integer.MAX_VALUE;
longminValue = Integer.MIN_VALUE;
longrange = maxValue - minValue + 1;
for (inti = 0; i < arr.length; i++) {
arr[i] = (int) (minValue + random.nextLong(range));
}
Integer[] copy = newInteger[arr.length];
System.arraycopy(arr, 0, copy, 0, arr.length);
longstart = System.currentTimeMillis();
chenSort(arr);
longchenSortTimeUsage = System.currentTimeMillis() - start;
start = System.currentTimeMillis();
Arrays.sort(copy);
longquickSortTimeUsage = System.currentTimeMillis() - start;
chensort: 3384ms, quicksort: 9366ms, 63.869314541960286%(2.767730496453901x) fasterchensort: 3450ms, quicksort: 7223ms, 52.2359130555171%(2.093623188405797x) fasterchensort: 1693ms, quicksort: 5000ms, 66.14%(2.9533372711163617x) fasterchensort: 2306ms, quicksort: 6267ms, 63.204084889101644%(2.717692974848222x) fasterchensort: 2922ms, quicksort: 10145ms, 71.19763430261213%(3.471937029431896x) fasterchensort: 3285ms, quicksort: 9211ms, 64.33611985669309%(2.803957382039574x) fasterchensort: 2661ms, quicksort: 9236ms, 71.18882633174535%(3.4708756106726795x) fasterchensort: 2538ms, quicksort: 6422ms, 60.47960137028963%(2.530338849487786x) fasterchensort: 1749ms, quicksort: 4928ms, 64.50892857142857%(2.8176100628930816x) fasterchensort: 1775ms, quicksort: 5254ms, 66.21621621621621%(2.96x) fasterchensort: 1626ms, quicksort: 5155ms, 68.45780795344326%(3.1703567035670357x) fasterchensort: 2375ms, quicksort: 4877ms, 51.302029936436334%(2.0534736842105263x) fasterchensort: 1923ms, quicksort: 5250ms, 63.37142857142857%(2.730109204368175x) fasterchensort: 3028ms, quicksort: 9237ms, 67.21879398072967%(3.0505284015852046x) fasterchensort: 2692ms, quicksort: 9030ms, 70.18826135105205%(3.3543833580980684x) faster

Blog

XiSort The slowest sorting algorithm I've developed with the most efficient code execution in the world.

Support me

If it helps you a lot, consider sponsoring me a cup of milk tea, or giving a star. Your support is the driving force for me to continue to maintain.

Paypal

sponsorship.webp

Thanks to the following netizens for their sponsorship.

  1. 小小鸟 2022.06.08
  2. 孟焱 2022.06.08

About

The world's fastest general purpose sorting algorithm, 60% faster than Quicksort

Resources

Stars

78 stars

Watchers

3 watching

Forks

Releases

Packages

Used by

Contributors

Languages