Sort
ValveBlog: AS3 sorting algorithm faster than native sorting
package { import flash.display.Sprite; import flash.utils.getTimer;
/** * Vector sorting methods test * * @author Eugene Zatepyakin * @see http://blog.inspirit.ru/?p=271 */ public class Main extends Sprite { public function Main() { test(); } private function test():void { var t:int = 100000; var arr:Vector.<Number> = new Vector.<Number>(t, true); var arr2:Array = []; var arr1:Vector.<Number>; for (var i:int = 0; i < t; i++) { var nn:Number = 1000 - Math.random() * 2000; arr[i] = nn; arr2[i] = nn; // this one is for built in array.sort } var tt:int; // Quick Sort + Insertion Sort // I guess this one could be faster // if we only could merge two functions in to one arr1 = arr.concat(); tt = getTimer(); qsort(arr1, 0, int(t - 1)); InsertionSort(arr1, 0, int(t - 1)); trace('qsort+insert:', getTimer() - tt); //checkSort(arr1); // 3 Way Quick Sort arr1 = arr.concat(); tt = getTimer(); qsort3Way(arr1, 0, int(t - 1)); trace('3way qsort:', getTimer() - tt); //checkSort(arr1); // Non Recursive Quick Sort arr1 = arr.concat(); tt = getTimer(); nonRecursiveQuickSort(arr1, 0, int(t - 1)); trace('non recursive qsort:', getTimer() - tt); //checkSort(arr1); // Optimized Non recursive qsort arr1 = arr.concat(); tt = getTimer(); OptNonRecursiveQuickSort(arr1, 0, (t - 1)); trace('opt non recursive qsort:', getTimer() - tt); //checkSort(arr1); // Non Recursive qsort 2 arr1 = arr.concat(); tt = getTimer(); nonRecursiveQsort2(arr1, t); trace('non recursive qsort2:', getTimer() - tt); //checkSort(arr1); // Flash Sort arr1 = arr.concat(); tt = getTimer(); flashSort(arr1, t); res += '\nFlash Sort\t\t\t\t\t' + (getTimer() - tt).toString(); //checkSort(arr1); // Built in Array sort tt = getTimer(); arr2.sort(Array.NUMERIC); trace('array.sort:', getTimer() - tt); } public function InsertionSort(arr:Vector.<Number>, n:int):void { var i:int, j:int, v:Number; for(j = 1; j < n; ++j) { v = arr[j]; i = int(j - 1); while(i >= 0 && arr[i] > v) arr[int(i+1)] = arr[ int(i--) ]; arr[int(i+1)] = v; } } public function qsort(arr:Vector.<Number>, l:int, r:int):void { var i:int, j:int, k:int, vi:int, v:Number; if ((r - l) > 10) { i = int(r + l) >> 1; if (arr[l] > arr[i]) { vi = arr[l]; arr[l] = arr[i]; arr[i] = vi; } if (arr[l] > arr[r]) { vi = arr[l]; arr[l] = arr[r]; arr[r] = vi; } if (arr[l] > arr[r]) { vi = arr[i]; arr[i] = arr[r]; arr[r] = vi; } j = int(r - 1); vi = arr[i]; arr[i] = arr[j]; arr[j] = vi; i = l; v = arr[j]; while (true) { while (arr[ int(++i) ] < v); while (arr[ int(--j) ] > v); if (j < i) break; vi = arr[i]; arr[i] = arr[j]; arr[j] = vi; } vi = arr[i]; arr[i] = arr[ (k = int(r - 1)) ]; arr[k] = vi; qsort(arr, l, j); qsort(arr, int(++i), r); } } private function qsort3Way(arr:Vector.<Number>, l:int, r:int):void { if((r - l) <= 10) return; var i:int = int(l - 1), j:int = r, p:int = int(l - 1), q:int = r, vi:Number; //if (r <= l) return; var v:Number = arr[r]; while (true) { while (arr[ int(++i) ] < v); while (v < arr[ int(--j) ]) { if (j == l) break; } if (i >= j) break; vi = arr[i]; arr[i] = arr[j]; arr[j] = vi; if (arr[i] == v) { vi = arr[ int(++p) ]; arr[p] = arr[i]; arr[i] = vi; } if (v == arr[j]) { vi = arr[j]; arr[j] = arr[ int(--q) ]; arr[q] = vi; } } vi = arr[i]; arr[i] = arr[r]; arr[r] = vi; j = int(i - 1); i = int(i + 1); for (var k:int = l; k < p; ++k, --j) { vi = arr[k]; arr[k] = arr[j]; arr[j] = vi; } for (k = (r - 1); k > q; --k, ++i) { vi = arr[i]; arr[i] = arr[k]; arr[k] = vi; } qsort3Way(arr, l, j); qsort3Way(arr, i, r); } public function nonRecursiveQuickSort(arr:Vector.<Number>, min:int, max:int):void { var Stack:Vector.<int> = new Vector.<int>(128, true); // Stack for array bounds var top:int = -1; var n:int = int(max + 1); var pivot:Number, temp:Number; var pivotindex:int, l:int, r:int, i:int, j:int; Stack[ int(++top) ] = min; // Initialize stack Stack[ int(++top) ] = max; while (top > 0) // While there are unprocessed subarrays { // Pop Stack j = Stack[ int(top--) ]; i = Stack[ int(top--) ]; // Findpivot pivotindex = int(i+j) >> 1; pivot = arr[pivotindex]; // Stick pivot at end arr[pivotindex] = arr[j]; arr[j] = pivot; // Partition l = (i - 1); r = j; do { while (arr[ int(++l) ] < pivot); while ((r!=0) && (arr[ int(--r) ] > pivot)); temp = arr[l]; arr[l] = arr[r]; arr[r] = temp; } while (l < r); // Undo final swap temp = arr[l]; arr[l] = arr[r]; arr[r] = temp; // Put pivot value in place temp = arr[l]; arr[l] = arr[j]; arr[j] = temp; // Put new subarrays onto Stack if they are small if ((l-i) > 10) // Left partition / 10 could be adjusted from 0 - … { Stack[ int(++top) ] = i; Stack[ int(++top) ] = (l-1); } if ((j-l) > 10) // Right partition / 10 could be adjusted from 0 - … { Stack[ int(++top) ] = (l+1); Stack[ int(++top) ] = j; } } for(j = 1; j < n; ++j) { temp = arr[j]; i = int(j - 1); while(i >= 0 && arr[i] > temp) arr[int(i+1)] = arr[ int(i--) ]; arr[int(i+1)] = temp; } } public function OptNonRecursiveQuickSort(c:Vector.<Number>, min:int, max:int):void { var i:int, j:int, left:int = min, right:int = max, stack_pointer:int = -1; var median:int; var stack:Vector.<int> = new Vector.<int>(128, true); var swap:Number, temp:Number; while(true){ if(right - left <= 10) // use insertion sort { for(j = int(left+1); j <= right; ++j) { swap = c[j]; i = int(j - 1); while(i >= left && c[i] > swap) c[int(i+1)] = c[ int(i--) ]; c[int(i+1)] = swap; } if(stack_pointer == -1) break; right = stack[ int(stack_pointer--) ]; left = stack[ int(stack_pointer--) ]; } else { median = int(left + right) >> 1; i = (left + 1); j = right; swap = c[median]; c[median] = c[i]; c[i] = swap; if(c[left] > c[right]) { swap = c[left]; c[left] = c[right]; c[right] = swap; } if(c[i] > c[right]) { swap = c[i]; c[i] = c[right]; c[right] = swap; } if(c[left] > c[i]) { swap = c[left]; c[left] = c[i]; c[i] = swap; } temp = c[i]; while(true){ //do i++; while(c[i] < temp); //do j--; while(c[j] > temp); while(c[ int(++i) ] < temp); while(c[ int(--j) ] > temp); if(j < i) break; swap = c[i]; c[i] = c[j]; c[j] = swap; } c[int(left + 1)] = c[j]; c[j] = temp; if((right-i+1) >= (j-left)) { stack[ int(++stack_pointer) ] = i; stack[ int(++stack_pointer) ] = right; right = int(--j); } else { stack[ int(++stack_pointer) ] = left; stack[ int(++stack_pointer) ] = int(--j); left = i; } } } } public function nonRecursiveQsort2(arr:Vector.<Number>, els:int):void { var piv:Number, i:int = 0, j:int, L:int, R:int; var beg:Vector.<int> = new Vector.<int>(128, true); var end:Vector.<int> = new Vector.<int>(128, true); beg[0] = 0; end[0] = els; while (i >= 0) { L = beg[i]; R = end[i] - 1; if (L < R) { piv = arr[L]; while (L < R) { while (arr[R] >= piv && L<R) --R; if (L<R) arr[ int(L++) ] = arr[R]; while (arr[L] <= piv && L<R) ++L; if (L<R) arr[ int(R--) ] = arr[L]; } arr[L] = piv; beg[ (j = int(i+1)) ] = (L+1); end[j] = end[i]; end[ int(i++) ] = L; } else { --i; } } } public function flashSort(a:Vector.<Number>, n:int):void { var i:int = 0, j:int = 0, k:int = 0, t:int; var m:int = int(n * .125); var l:Vector.<int> = new Vector.<int>(m); var anmin:Number = a[0]; var nmax:int = 0; var nmove:int = 0; for (i = 1; i < n; ++i) { if (a[i] < anmin) anmin = a[i]; if (a[i] > a[nmax]) nmax = i; } if (anmin == a[nmax]) return; var c1:Number = (m - 1) / (a[nmax] - anmin); for (i = 0; i < n; ++i) { k = int(c1*(a[i] - anmin)); ++l[k]; } for (k = 1; k < m; ++k) { l[k] += l[int(k-1)]; } var hold:Number = a[nmax]; a[nmax] = a[0]; a[0] = hold; var flash:Number; j = 0; k = int(m - 1); i = int(n - 1); while (nmove < i) { while (j > (l[k]-1)) { k = int(c1 * (a[ int(++j) ] - anmin)); } flash = a[j]; while (!(j == l[k])) { k = int(c1 * (flash - anmin)); hold = a[ (t = int(l[k]-1)) ]; a[ t ] = flash; flash = hold; --l[k]; ++nmove; } } for(j = 1; j < n; ++j) { hold = a[j]; i = int(j - 1); while(i >= 0 && a[i] > hold) a[int(i+1)] = a[ int(i--) ]; a[int(i+1)] = hold; } } public function checkSort(arr:Vector.<Number>):void { var n:int = arr.length; for (var i:int = 1; i < n; ++i) { if (arr[int(i - 1)] > arr[i]) { trace("bad sort"); return; } } trace('sort ok'); } }
}
package { import flash.display.Sprite; import flash.events.Event; import flash.utils.getTimer;
public class Sorting extends Sprite { public function Sorting() { addEventListener(Event.ENTER_FRAME, loop); } private function loop(e:Event):void { var data:Vector.<Number> = new Vector.<Number>(); for(var i:int = 0; i<10000; i++){ data.push(Math.random()*10000); } var data2:Vector.<Number> = data.concat(); var t:Number = getTimer(); data.sort(sf); trace("Native sort", (getTimer()-t)); t = getTimer(); data.sort(sf); trace("Native sort on ordered elements", (getTimer()-t)); t = getTimer(); shellSort(data2); trace("AS3 Shell sort", (getTimer()-t)); t = getTimer(); shellSort(data2); trace("AS3 Shell sort on ordered elements", (getTimer()-t)); } final private function sf(a:Number, b:Number):int { return (a==b ? 0 : (a < b) ? -1 : 1); } final private function shellSort(data:Vector.<Number>):void { var n:int = data.length; var inc:int = int(n/2); while(inc) { for(var i:int=inc; i<n; i++) { var temp:Number = data[i], j:int = i; while(j >= inc && data[int(j - inc)] > temp) { data[j] = data[int(j - inc)]; j = int(j - inc); } data[j] = temp } inc = int(inc / 2.2); } } }
}
Last updated