@@ -15,7 +15,7 @@ class ChenSortExample extends StatefulWidget {
1515}
1616
1717class ChenSortExampleState extends State <ChenSortExample > {
18- int defaultNumberCount = 10000 ;
18+ int defaultNumberCount = 100000 ;
1919 late TextEditingController numberCountController =
2020 TextEditingController (text: '$defaultNumberCount ' );
2121 List <String > sortResult = [];
@@ -31,11 +31,12 @@ class ChenSortExampleState extends State<ChenSortExample> {
3131 ),
3232 body: ConstraintLayout ().open (() {
3333 const Text (
34- 'The time complexity is O(n), the space complexity is O(n), and it is stable' ,
34+ 'The time complexity is O(n) at best and O(nlog2n) at worst , the space complexity is O(n), and it is stable' ,
3535 style: TextStyle (
3636 fontSize: 30 ,
3737 ),
3838 ).applyConstraint (
39+ maxWidth: 800 ,
3940 topCenterTo: parent,
4041 );
4142 TextField (
@@ -45,7 +46,7 @@ class ChenSortExampleState extends State<ChenSortExample> {
4546 ),
4647 inputFormatters: [FilteringTextInputFormatter .digitsOnly],
4748 ).applyConstraint (
48- width: 500 ,
49+ width: 800 ,
4950 outBottomCenterTo: sId (- 1 ).topMargin (20 ),
5051 );
5152 ElevatedButton (
@@ -98,36 +99,93 @@ class ChenSortExampleState extends State<ChenSortExample> {
9899
99100String compareSort (int numbers) {
100101 Random random = Random ();
101- var arr = [for (int i = 0 ; i < numbers; i++ ) random.nextInt (4294967296 )];
102+ var arr = [
103+ for (int i = 0 ; i < numbers; i++ ) - 2 ^ 63 + random.nextInt (2 ^ 63 )
104+ ];
102105 List copy = List .of (arr);
103106 Stopwatch stopwatch = Stopwatch ()..start ();
107+ stopwatch.reset ();
104108 chenSort (arr);
105109 int chenSortTimeUsage = stopwatch.elapsedMicroseconds;
106110 stopwatch.reset ();
107111 copy.sort ();
108112 int quickSortTimeUsage = stopwatch.elapsedMicroseconds;
109113 double percent =
110114 ((quickSortTimeUsage - chenSortTimeUsage) / quickSortTimeUsage) * 100 ;
111- return 'chen sort time usage = $ chenSortTimeUsage us, quick sort time usage = $quickSortTimeUsage us, ${percent .toStringAsFixed (2 )}% faster' ;
115+ return 'Are the sorted results equal? ${ listEquals ( arr , copy )}, chen sort: $ chenSortTimeUsage us, quick sort: $quickSortTimeUsage us, ${percent .toStringAsFixed (2 )}%(${( quickSortTimeUsage / chenSortTimeUsage ). toStringAsFixed ( 1 )}x) faster' ;
112116}
113117
118+ /// The essence of Chen Sort is an improved bucket sort
114119void chenSort (List <int > list) {
115- int max = - 2 ^ 63 ;
116- for (final element in list) {
117- if (element > max) {
118- max = element;
120+ if (list.length < 2 ) {
121+ return ;
122+ }
123+
124+ int maxValue = list[0 ];
125+ int minValue = maxValue;
126+ for (final element in list.skip (1 )) {
127+ if (element > maxValue) {
128+ maxValue = element;
129+ }
130+ if (element < minValue) {
131+ minValue = element;
119132 }
120133 }
134+
135+ /// All elements are the same and do not need to be sorted.
136+ if (maxValue == minValue) {
137+ return ;
138+ }
139+
140+ /// Limit the maximum size of the bucket to ensure the performance of long list
141+ /// sorting, which can be adjusted according to the actual situation.
142+ ///
143+ /// The essential difference between this and bucket sorting is that the size of
144+ /// the bucket is only related to the length of the list, not the range of element values.
145+ int bucketSize = min (list.length, 50000 );
146+ int maxBucketIndex = bucketSize - 1 ;
147+
148+ List <List <int >?> buckets = List .filled (bucketSize, null );
121149 int slot;
122- List <List <int >?> buckets = List .filled (list.length + 1 , null );
123- double factor = list.length / max;
124- for (final element in list) {
125- slot = (element * factor).toInt ();
126- if (buckets[slot] == null ) {
127- buckets[slot] = [];
150+
151+ /// Calculate the bucket in which the element is located based on the value of the element
152+ /// and the maximum and minimum values.
153+
154+ /// Overflow detection
155+ BigInt range = BigInt .from (maxValue - minValue);
156+ if (BigInt .from (range.toInt ()) == range) {
157+ int range = maxValue - minValue;
158+ double factor = maxBucketIndex / range;
159+ for (final element in list) {
160+ // slot = (((element - minValue) / range) * maxBucketIndex).toInt();
161+ slot = ((element - minValue) * factor).toInt ();
162+ if (buckets[slot] == null ) {
163+ buckets[slot] = [];
164+ }
165+ buckets[slot]! .add (element);
166+ }
167+ } else {
168+ /// Overflowed(positive minus negative)
169+ int positiveRange = maxValue;
170+ int negativeRange = - minValue - 1 ;
171+ int positiveStartBucketIndex = maxBucketIndex ~ / 2 + 1 ;
172+ int positiveBucketLength = maxBucketIndex - positiveStartBucketIndex;
173+ int negativeBucketLength = positiveStartBucketIndex - 1 ;
174+ for (final element in list) {
175+ if (element < 0 ) {
176+ slot = (((element - minValue) / negativeRange) * negativeBucketLength)
177+ .toInt ();
178+ } else {
179+ slot = positiveStartBucketIndex +
180+ ((element / positiveRange) * positiveBucketLength).toInt ();
181+ }
182+ if (buckets[slot] == null ) {
183+ buckets[slot] = [];
184+ }
185+ buckets[slot]! .add (element);
128186 }
129- buckets[slot]! .add (element);
130187 }
188+
131189 int compare (int left, int right) {
132190 return left - right;
133191 }
@@ -136,10 +194,13 @@ void chenSort(List<int> list) {
136194 for (final bucket in buckets) {
137195 if (bucket != null ) {
138196 if (bucket.length > 1 ) {
197+ /// The sort method here represents the fastest comparison-type algorithm (Quick sort, Tim sort, etc.)
139198 bucket.sort (compare);
140- }
141- for (final element in bucket) {
142- list[index++ ] = element;
199+ for (final element in bucket) {
200+ list[index++ ] = element;
201+ }
202+ } else {
203+ list[index++ ] = bucket[0 ];
143204 }
144205 }
145206 }
0 commit comments