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.
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) fasterXiSort The slowest sorting algorithm I've developed with the most efficient code execution in the world.
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.
Thanks to the following netizens for their sponsorship.
- 小小鸟 2022.06.08
- 孟焱 2022.06.08
