1. Algorithmic thinking
If a sequence is to be sorted, all the numbers are already in the correct position, then the sorting is complete.
Just pick a number and put it in the right place. The left side is unsorted, and the right side is unsorted.
At this point, the problem of sorting on a longer series has been transformed into a sort of two smaller series.
Reference: http://developer.51cto.com/art/201403/430986.htm
Take sequence a = {6, 1, 2, 7, 9, 3, 4, 5, 10, 8} for example
2. In order to put 6 in the correct position (ascending), my first thought is: from the left to the right a number of a number and 6 compared to encounter a smaller than 6 to let it and 6 exchange, then wrote the following Java code (first implemented in Java, and then in Scala implementation)
package algorithm.qs;import java.util.arrays;public class qs { public static void main (String[] args) { integer[] a = {6 , 1, 2, 7, 9, 3, 4, 5, 10 , 8}; int k = 0; for (int i = 0; i < a.length; i++) { if (A[i] < a[k]) { int t = a[i]; a[i] = a[k]; a[k] = t; k = i; } } system.out.println (Arrays.deeptostring (a)); }}//[1, 2, 3, 7, &NBSP;9,&NBSP;4,&NBSP;5,&NBSP;6,&NBSP;10,&NBSP;8]
But there is a problem: 6 smaller than the 6 to the left, than the 6 is not ranked to the right of 6.
3. Then improve the algorithm, if the encounter than 6 small number B, the number between 6 and B (including 6 does not include B) Move backward 1 bits, put B in the original 6 position
package algorithm.qs;import java.util.arrays;public class qs { static Integer[] a = { 6, 1, 2, 7, 9, 3, 4, 5,&NBSP;10,&NBSP;8&NBSP;};&NBSP;&NBSP;&NBSP;&NBSP;//&NBSP;[...I...J ...] => [...j...i ...] static void swap (INT&NBSP;I,&NBSP;INT&NBSP;J) { int t = a[i]; a[i] = a[j]; a[j] = t; } // [...abcd ...] => [...dabc ...] static void move (INT&NBSP;I,&NBSP;INT&NBSP;J) { while (I&NBSP;<&NBSP;J) { swap (j-1, j); j--; } } // will be greater than the first number on the right of the first digit, less than the first number on the first digit left static void divide () { int k = 0; for (int i = 0; i < a.length; i++) { if (A[i] < a[k]) { move (k, i); k++; } } } public static vOid main (String[] args) { divide (); system.out.println (Arrays.deeptostring (a)); }}//[1, &NBSP;2,&NBSP;3,&NBSP;4,&NBSP;5,&NBSP;6,&NBSP;7,&NBSP;9,&NBSP;10,&NBSP;8]
4. How can I sort the entire array without changing too much code? If you want to sort the left and right of 6, you need to divide the part of a. Now the Divide method is implemented to put the first number of the entire array in the correct position, can you give it a part of the array, let it put the first number of this part in the correct position?
The improved divide
package algorithm.qs;import java.util.arrays;public class qs { final static integer[] a = { 6, 1, 2, 7, 9, 3, &NBSP;4,&NBSP;5,&NBSP;10,&NBSP;8&NBSP;};&NBSP;&NBSP;&NBSP;&NBSP;//&NBSP;[...I...J ...] => [...j...i ...] static void swap (INT&NBSP;I,&NBSP;INT&NBSP;J) { int t = a[i]; a[i] = a[j]; a[j] = t; } // [...abcd ...] => [...dabc ...] static void move (INT&NBSP;I,&NBSP;INT&NBSP;J) { while (I&NBSP;<&NBSP;J) { swap (j-1, j); j--; } } /* * The number of positions between S and T is divided into two (including s not including T) * is greater than the number of S number on the right, less than the number of s on the left of the number of numbers */ static int divide (int s, int t) { int k = s; for (int i = s; i < t; i++) { if (A[i] < a[k]) { move (k, i); k++; } } return k; } static void qsort ( INT&NBSP;S,&NBSP;INT&NBSP;T) { int mid = Divide (s, t); system.out.println (mid); } public static void main (String[] args) { qsort (0, a.length); system.out.println (Arrays.deeptostring (a)); }}//5//[1, 2, &NBSP;3,&NBSP;4,&NBSP;5,&NBSP;6,&NBSP;7,&NBSP;9,&NBSP;10,&NBSP;8]
5. Last step recursive call Qsort
package algorithm.qs;import java.util.arrays;public class qs { final static integer[] a = { 6, 1, 2, 7, 9, 3, &NBSP;4,&NBSP;5,&NBSP;10,&NBSP;8&NBSP;};&NBSP;&NBSP;&NBSP;&NBSP;//&NBSP;[...I...J ...] => [...j...i ...] static void swap (INT&NBSP;I,&NBSP;INT&NBSP;J) { int t = a[i]; a[i] = a[j]; a[j] = t; } // [...abcd ...] => [...dabc ...] static void move (INT&NBSP;I,&NBSP;INT&NBSP;J) { while (I&NBSP;<&NBSP;J) { swap (j-1, j); j--; } } /* * The number of positions between S and T is divided into two (including s not including T) * is greater than the number of S number on the right, less than the number of s on the left of the number of numbers */ static int divide (int s, int t) { int k = s; for (int i = s; i < t; i++) { if (A[i] < a[k]) { move (k, i); k++; } } return k; } static void qsort ( INT&NBSP;S,&NBSP;INT&NBSP;T) { int mid = Divide (s, t); if (mid > s) qsort (S, mid); if (t > mid + 1) Qsort (mid+1, t); } public Static void main (String[] args) { qsort (0, a.length); system.out.println (Arrays.deepToString (a)); &NBSP;&NBSP;&NBSP;&NBSP;}}//[1,&NBSP;2,&NBSP;3,&NBSP;4,&NBSP;5,&NBSP;6,&NBSP;7,&NBSP;8,&NBSP;9,&NBSP;10]
6. Code Reviews
Although the above code realizes the basic idea of fast sorting, it doesn't show up fast. The time complexity is similar to the insertion sort and bubble sort. The reason is that the move method has too many exchanges. Mathematically speaking, a single exchange reduces the number of reverse order. Fast sorting really embodies the fast place is "jumping" to exchange nonadjacent two numbers, so that the number of reverse order "may" reduce a lot. Below we continue to improve the divide method. This time, two pointers are used to iterate through the array from each end.
package algorithm.qs;import java.util.arrays;public class qs { final static integer[] a = { 6, 1, 2, 7, 9, 3, 4, 5, 10, 8 }; static void Swap (INT&NBSP;I,&NBSP;INT&NBSP;J) { int t = a[i]; a[i] = a[j]; a[j] = t; } /* * divides the number of positions between S and T into two dials (including S excluding T) * is greater than the number of numbers on the right of the number of s, less than the number of s on the left side of the number of S */ static int Divide (int s, int t) { int i = s, j = t; while (I&NBSP;<&NBSP;J) { if (A[j] < a[s]) { while (I&NBSP;<&NBSP;J) { if (A[i] > a[s]) { swap (I,&NBSP;J); break; } i++; } } if (I&NBSP;<&NBSP;J) j--; } swap (S,&NBSP;J); return j; } static void qsort (int s, int t) { int mid = divide (s, t); if (mid > s) qsort (s, mid); if ( t > mid + 1) qsort (mid+1, t); } publiC static void main (String[] args) { Qsort (0, a.length-1); system.out.println ( Arrays.deeptostring (a)); }}
The above code is at least two points not beautiful: 1. All methods have side effects, especially the divide method, which modifies both the external variable and the return value. 2. While, for, if layer nesting makes the code idea very intuitive
7. The Scala version of Quick sort
Package play1object p extends app { def qsort (List: List[Int]): list[int] = list match { case nil => nil case pivot :: tail => val (smaller, rest) = tail.partition (_ < pivot) qsort (smaller) ::: pivot :: qsort (rest) } val a = list (6, 1, 2, 7, 9, 3, 4, 5, 10, 8) val b = qsort (a) println (b)} // was excerpted from the Scala source Def partition (p: A = > boolean): (REPR,&NBSP;REPR) = { val l, r = newbuilder for (x <- this) (if (P (x)) l else r) += x (l.result, r.reSult)}
This is a complete function of the implementation, although the partition method a little bit of space to change the sense of time. It's not really useful to have a swap here, and the idea is clear.
Play Scala 71 Step-by-step quicksort