Several common sorting algorithms implemented in Java

Source: Internet
Author: User
1. Select sort

The basic idea of sorting is to use I to represent the sequence number to be sorted in the Process of traversing the array... N-1] To find the minimum value, and then exchange the minimum value with the value pointed to by I. Because each process of determining an element has a subflow that selects the maximum value, it is vividly called "select sorting.

For example:

Initial: [38, 17, 16, 16, 7, 31, 39, 32, 2, 11]

I = 0: [2, 17, 16, 16, 7, 31, 39, 32, 38, 11] (0th [38] <-> 8th [2])

I = 1: [2, 7, 16, 16, 17, 31, 39, 32, 38, 11] (1st [38] <-> 4th [17])

I = 2: [2, 7, 11, 16, 17, 31, 39, 32, 38, 16] (2nd [11] <-> 9th [16])

I = 3: [2, 7, 11, 16, 17, 31, 39, 32, 38, 16] (no exchange required)

I = 4: [2, 7, 11, 16, 16, 31, 39, 32, 38, 17] (4th [17] <-> 9th [16])

I = 5: [2, 7, 11, 16, 16, 17, 39, 32, 38, 31] (5th [31] <-> 9th [17])

I = 6: [2, 7, 11, 16, 16, 17, 31, 32, 38, 39] (6th [39] <-> 9th [31])

I = 7: [2, 7, 11, 16, 16, 17, 31, 32, 38, 39] (no exchange required)

I = 8: [2, 7, 11, 16, 16, 17, 31, 32, 38, 39] (no exchange required)

I = 9: [2, 7, 11, 16, 16, 17, 31, 32, 38, 39] (no exchange required)

From the example, we can see that the number of comparisons increases with the sorting (I gradually increases), but no matter whether the array is sorted or not, when sorting is selected, a comparison is performed from I to the end of the array. Therefore, the number of comparisons selected for an array with a given length is fixed: 1 + 2 + 3 + .... + N = N * (n + 1)/2, and the number of exchanges is related to the order of the initial array. If the initial array order is random, in the worst case, the array elements are exchanged for n times. In the best case, it may be 0 times (the array itself is ordered ).

Therefore, we can introduce that the time complexity and space complexity of sorting are O (n2) and O (1) respectively (only one additional space is required for array element exchange ).

Implementation Code:

/** * Selection Sorting */SELECTION(new Sortable() {public <T extends Comparable<T>> void sort(T[] array, boolean ascend) {int len = array.length;for (int i = 0; i < len; i++) {int selected = i;for (int j = i + 1; j < len; j++) {int compare = array[j].compareTo(array[selected]);if (compare != 0 && compare < 0 == ascend) {selected = j;}}exchange(array, i, selected);}}})
2. Insert sorting

The basic idea of inserting sorting is to traverse the array. Assume that the element before sequence number I is [0 .. i-1] have been sorted, this trip needs to find the correct position of the I corresponding element x K, in addition, in the process of searching for this position K, the comparison elements are moved one by one to change the position of the element x. Finally, the corresponding element value of K is assigned to X, insert sorting is also named based on the sorting feature.

The following is an example. The numbers marked in red are the inserted numbers. The excluded numbers are the elements not involved in this sorting, the elements between the numbers marked in red and the number to be crossed are moving backward one by one. For example, the elements involved in the second sorting are [11, 31, 12], the element to be inserted is 12, but 12 is not currently in the correct position, so we need to compare it with the previous elements 31 and 11, and move the compared elements while comparing them, when the first element 11 is found to be smaller than 12, the comparison is stopped. At this time, Index 1 corresponding to 31 is the location where 12 needs to be inserted.

Initial: [11, 31, 12, 5, 34, 30, 26, 38, 36, 18]

First trip: [11, 31, 12, 5, 34, 30, 26, 38, 36, 18] (no moving element)

Second trip: [11, 12, 31, 5, 34, 30, 26, 38, 36, 18] (31 backward moving)

Third trip: [5, 11, 12, 31, 34, 30, 26, 38, 36, 18] (11, 12, 31 move backwards)

Fourth: [5, 11, 12, 31, 34, 30, 26, 38, 36, 18] (no moving element)

Fifth: [5, 11, 12, 30, 31, 34, 26, 38, 36, 18] (31, 34 move backward)

Sixth: [5, 11, 12, 26, 30, 31, 34, 38, 36, 18] (30, 31, 34 move backward)

Seventh: [5, 11, 12, 26, 30, 31, 34, 38, 36, 18] (no moving element)

Eighth trip: [5, 11, 12, 26, 30, 31, 34, 36, 38, 18] (38 backward moving)

9: [5, 11, 12, 18, 26, 30, 31, 34, 36, 38] (26, 30, 31, 34, 36, 38)

Insert sorting is better than select sorting. The reason is that it can effectively reduce the number of comparisons by taking advantage of the fact that the previous array elements have already sorted the order, of course, this advantage depends on the initial order of the array. In the worst case (the given array is in reverse order) the number of insert sort operations that need to be compared and moved will be equal to 1 + 2 + 3... + N = N * (n + 1)/2. In extreme cases, insertion sorting is more efficient than selection sorting. Therefore, insertion sorting is an unstable sorting method, and the insertion efficiency is closely related to the initial order of the array. Generally, the time complexity and space complexity of insertion sorting are O (n2) and O (1), respectively).

Implementation Code:

/** * Insertion Sorting */INSERTION(new Sortable() {public <T extends Comparable<T>> void sort(T[] array, boolean ascend) {int len = array.length;for (int i = 1; i < len; i++) {T toInsert = array[i];int j = i;for (; j > 0; j--) {int compare = array[j - 1].compareTo(toInsert);if (compare == 0 || compare < 0 == ascend) {break;}array[j] = array[j - 1];}array[j] = toInsert;}}})


3. Bubble Sorting

Bubble Sorting can be regarded as the most classic sorting algorithm. I remember that this algorithm was first introduced when my younger brother went to school, because the implementation method is the simplest and has two-layer for loop, when two adjacent elements are in reverse order in a layer-1 loop, the minimum elements in the array can be "floated" to the beginning once the two elements are exchanged, so it is called Bubble sorting.

Take a simple example as follows:

Initial status: [24, 19, 26, 39, 36, 7, 31, 29, 38, 23]

The first entry in the inner layer: [24, 19, 26, 39, 36, 7, 31, 29, 23, 38] (9th [23] <-> 8th [38)

Second inner layer: [24, 19, 26, 39, 36, 7, 31, 23, 29, 38] (8th [23] <-> 7th [29])

The third layer: [24, 19, 26, 39, 36, 7, 23, 31, 29, 38] (7th [23] <-> 6th [31])

The fourth entry in the inner layer: [24, 19, 26, 39, 36, 7, 23, 31, 29, 38] (7 and 23 are in the correct order and do not need to be exchanged)

Fifth inner layer: [24, 19, 26, 39, 7, 36, 23, 31, 29, 38] (5th [7] <-> 4th [36])

Sixth inner layer: [24, 19, 26, 7, 39, 36, 23, 31, 29, 38] (4th [7] <-> 3rd [39])

Inner Layer 7: [24, 19, 7, 26, 39, 36, 23, 31, 29, 38] (3rd [7] <-> 2nd [26])

Inner Layer Eighth: [24, 7, 19, 26, 39, 36, 23, 31, 29, 38] (2nd [7] <-> 1st [19])

Inner Layer 9: [7, 24, 19, 26, 39, 36, 23, 31, 29, 38] (1st [7] <-> 0th [24])

......

In fact, the Bubble Sorting is similar to the selected sorting. The number of comparisons is the same. All values are N * (n + 1)/2, however, the bubble sort performs an additional exchange in the process of selecting the minimum value (in the sorting process, if the order of the adjacent elements is not correct, the bubble sort will be exchanged, which corresponds to the selection sorting, it will only determine whether to exchange after the internal loop comparison ends), so in my opinion, selecting the sort version of the Bubble Sorting is selected.

Implementation Code:

/** * Bubble Sorting, it's very similar with Insertion Sorting */BUBBLE(new Sortable() {public <T extends Comparable<T>> void sort(T[] array, boolean ascend) {int length = array.length;int lastExchangedIdx = 0;for (int i = 0; i < length; i++) {// mark the flag to identity whether exchange happened to falseboolean isExchanged = false;// last compare and exchange happened before reaching index iint currOrderedIdx = lastExchangedIdx > i ? lastExchangedIdx : i;for (int j = length - 1; j > currOrderedIdx; j--) {int compare = array[j - 1].compareTo(array[j]);if (compare != 0 && compare > 0 == ascend) {exchange(array, j - 1, j);isExchanged = true;lastExchangedIdx = j;}}// if no exchange happen means array is already in orderif (isExchanged == false) {break;}}}})


4. Hill sorting

The birth of hill sorting is due to the need to move too many elements when inserting sorting to process large-scale arrays. The idea of hill sorting is to divide a large array into several small arrays by gap, such as arrays [1, 2, 3, 4, 5, 6, 7, 8], if divided by Gap = 2, it can be divided into [1, 3, 5, 7] and [2, 4, 6, 8] Two arrays (corresponding, for example, Gap = 3) are divided into: [1, 4, 7], [2, 5, 8], [3,
6]) insert and sort the divided arrays separately. After the sub-arrays are sorted, reduce the gap value and repeat the previous steps until Gap = 1, insert and sort the entire array. At this time, the array is almost sorted, so the elements to be moved are very small, it solves the problem that insertion sorting is more frequently moved when processing large-scale arrays.

For specific instances, see insert sorting.

Hill sorting is the simplified version of insert sorting, which greatly improves efficiency when there is a large amount of data. It is recommended to directly use insert sorting when there is a small amount of data.

Implementation Code:

/** * Shell Sorting */SHELL(new Sortable() {public <T extends Comparable<T>> void sort(T[] array, boolean ascend) {int length = array.length;int gap = 1;// use the most next to length / 3 as the first gapwhile (gap < length / 3) {gap = gap * 3 + 1;}while (gap >= 1) {for (int i = gap; i < length; i++) {T next = array[i];int j = i;while (j >= gap) {int compare = array[j - gap].compareTo(next);// already find its positionif (compare == 0 || compare < 0 == ascend) {break;}array[j] = array[j - gap];j -= gap;}if (j != i) {array[j] = next;}}gap /= 3;}}})

5. Merge Sorting

Merging and sorting is implemented by recursion. The target array is divided into two parts from the center, and then the two arrays are sorted separately, after sorting, the two arrays in the sorting order are "merged". The most important part of the sorting is the "merge" process, during the merging process, an additional space must be consistent with the length of the two arrays to be merged. For example, the required arrays are: [3, 6, 8, 11] and [1, 3, 12, 15] (although logically divided into two arrays, these elements are still in the original array, but they are divided into two arrays by some indexes, the original array is [3,
6, 8, 11, 1, 3, 12, 15, we set three pointers Lo, mid, and high to 0, 3, and 7 respectively to implement logical sub-array division) the length of the required additional array is 4 + 4 = 8. The process of merging can be summarized as follows:

1) copy the elements in the two sub-arrays to the new copiedarray. For example, copiedarray = [3, 6, 8, 11, 1, 3, 12, 15];

2) set the two pointers to the first element corresponding to the atomic array. Assume that the two pointers are named leftidx and rightidx, then leftidx = 0 (corresponding to the first element in copiedarray [3]), rightidx = 4 (corresponding to the fifth element in copiedarray [1]);

3) Compare the array element values pointed by leftidx and rightidx, select a smaller one, and assign the value to the corresponding position I in the original array, after the assignment is complete, perform the auto-increment 1 operation on the two indexes involved in the assignment. If the leftidx or rigthidx value has reached the end of the corresponding array, then, you only need to copy the elements of the remaining array to the remaining position in order.

The following is a specific example of merging:

First trip:

Secondary array [21, 28, 39 | 35, 38] (the array is split into two subarrays, separated by |)

[21,] (the first comparison between 21 and 35, the left sub-array wins, leftidx = 0, I = 0)

Second trip:

Secondary array [21, 28, 39 | 35, 38]

[21, 28,] (the second comparison between 28 and 35, the left-side sub-array wins, leftidx = 1, I = 1)

Third trip: [21, 28, 39 | 35, 38]

[21, 28, 35,] (compared with 35 for the third time, the child array on the right wins, rightidx = 0, I = 2)

Fourth: [21, 28, 39 | 35, 38]

[21, 28, 35, 38,] (comparison between 39 and 38 for the fourth time, the right sub-array wins, rightidx = 1, I = 3)

Fifth: [21, 28, 39 | 35, 38]

[21, 28, 35, 38, 39] (when the fifth time, the child array on the right has been copied, you do not need to compare leftidx
= 2, I = 4)

The above is the process of merging. We can split the entire array to be sorted for a limited time (split each time) until it is divided into a small array with a length of 1, no sorting is required for the group with a length of 1. After that, merge these arrays in reverse order (due to recursion) until the last time the child array with the length of n/2 is merged, the array sorting is also completed.

The extra space required for Merge Sorting is the most among all sorts. Each merge must have the same element as the sum of the length of the two arrays involved in the merge (to provide an auxiliary array ). It can be inferred that the space complexity of Merge Sorting is 1 + 2 + 4 +... + N = N * (N + 2)/4 (ignore n's parity judgment). It is difficult to estimate the time complexity. Here, the younger brother forgets the time complexity ).

Implementation Code:

/** * Merge sorting */MERGE(new Sortable() {public <T extends Comparable<T>> void sort(T[] array, boolean ascend) {this.sort(array, 0, array.length - 1, ascend);}private <T extends Comparable<T>> void sort(T[] array, int lo, int hi, boolean ascend) {// OPTIMIZE ONE// if the substring's length is less than 20,// use insertion sort to reduce recursive invocationif (hi - lo < 20) {for (int i = lo + 1; i <= hi; i++) {T toInsert = array[i];int j = i;for (; j > lo; j--) {int compare = array[j - 1].compareTo(toInsert);if (compare == 0 || compare < 0 == ascend) {break;}array[j] = array[j - 1];}array[j] = toInsert;}return;}int mid = lo + (hi - lo) / 2;sort(array, lo, mid, ascend);sort(array, mid + 1, hi, ascend);merge(array, lo, mid, hi, ascend);}private <T extends Comparable<T>> void merge(T[] array, int lo, int mid, int hi, boolean ascend) {// OPTIMIZE TWO// if it is already in right order, skip this merge// since there's no need to do soint leftEndCompareToRigthStart = array[mid].compareTo(array[mid + 1]);if (leftEndCompareToRigthStart == 0 || leftEndCompareToRigthStart < 0 == ascend) {return;}@SuppressWarnings("unchecked")T[] arrayCopy = (T[]) new Comparable[hi - lo + 1];System.arraycopy(array, lo, arrayCopy, 0, arrayCopy.length);int lowIdx = 0;int highIdx = mid - lo + 1;for (int i = lo; i <= hi; i++) {if (lowIdx > mid - lo) {// left sub array exhaustedarray[i] = arrayCopy[highIdx++];} else if (highIdx > hi - lo) {// right sub array exhaustedarray[i] = arrayCopy[lowIdx++];} else if (arrayCopy[lowIdx].compareTo(arrayCopy[highIdx]) < 0 == ascend) {array[i] = arrayCopy[lowIdx++];} else {array[i] = arrayCopy[highIdx++];}}}})


For more information, see http://easense2009.iteye.com/blog/1568614

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.