method | average time | Worst time | Extra space | stability |
---|---|---|---|---|
Bubble sorting | O(n2) | O(n2) | O(1) | stable |
Select sort | O(n2) | O(n2) | O(1) | instable |
Insert sort | O(n2) | O(n2) | O(1) | stable |
Cardinality sort | O(d(n+r)) | O(d(n+r)) | O(d+r) | stable |
Shell Sort | O(nlogn) | O(n2) | O(1) | instable |
Quick sort | O(nlogn) | O(n2) | O(nlogn) | instable |
Merge sort | O(nlogn) | O(nlogn) | O(1) | stable |
Heap sort | O(nlogn) | O(nlogn) | O(1) | instable |
1. Insert sort
Basic idea: the n elements to be sorted are regarded as an ordered table and an unordered table. At the beginning, the ordered table contains only one element, and the unordered table contains n-1 elements. In the sorting process, the first element is taken out from the unordered table every time, its sorting code is compared with the sorting code of the elements of the ordered table in turn, and it is inserted into the appropriate position in the ordered table, Make it a new ordered table.
public static void insertSort(int[] arr) { if (null == arr || arr.length < 2) { return; } for (int i = 1; i < arr.length; i++) { int insertVal = arr[i]; int insertIndex = i - 1; // 1. Insertindex > = 0 ensures that the array is not out of bounds // 2. Insertval < arr [insertindex] indicates that a suitable position is not found and should be moved back // 3. Continue to compare forward while (insertIndex >= 0 && insertVal < arr[insertIndex]) { arr[insertIndex + 1] = arr[insertIndex]; insertIndex--; } // At this time, the insertion position has been found, that is, insertval > = arr [insertindex] arr[insertIndex + 1] = insertVal; } }
2. Hill sort
Basic principle - the records are grouped according to a certain increment of subscript, and the direct insertion sorting algorithm is used for each group; As the increment decreases, each group contains more and more keywords. When the increment decreases to 1, the whole file is just divided into one group, and the algorithm terminates
//Exchange method public static void shellSortSwap(int[] arr) { int temp = 0; for (int step = arr.length / 2; step > 0; step /= 2) { for (int i = step; i < arr.length; i++) { for (int j = i - step; j >= 0; j -= step) { if (arr[j] > arr[j + step]) { temp = arr[j]; arr[j] = arr[j + step]; arr[j + step] = temp; } } } } }
optimization
public static void shellSortMove(int[] arr) { for (int step = arr.length / 2; step > 0; step /= 2) { System.out.println("Step size" + step); for (int i = step; i < arr.length; i++) { int insertVal = arr[i]; int insertIndex = i - step; while (insertIndex >= 0 && insertVal < arr[insertIndex]) { arr[insertIndex + step] = arr[insertIndex]; insertIndex -= step; } arr[insertIndex + step] = insertVal; System.out.println(Arrays.toString(arr)); } } }
3. Select sort
Basic idea - find the smallest in the array and exchange with the first, then find the smallest and second exchange from the remaining elements, and so on
public static void selectSort(int[] arr) { if (null == arr || arr.length < 2) { return; } for (int i = 0; i < arr.length - 1; i++) { int min = arr[i]; int minIndex = i; for (int j = i + 1; j < arr.length; j++) { if (arr[j] < min) { min = arr[j]; minIndex = j; } } if (minIndex != i) { arr[minIndex] = arr[i]; arr[i] = min; } } }
Optimization: while selecting the minimum value each time, you can also select and exchange the maximum value to reduce the number of choices
4. Heap sort
Basic idea - build the initial heap, and form the sequence to be arranged into a large top heap (or small top heap), ascending large top heap and descending small top heap; Swap the heap top element with the heap tail element and disconnect (remove from the queue) the heap tail element. Rebuild the heap. Repeat the element exchange and build the heap until there is only one element left in the queue (the top element of the heap).
public static void heapSort(int[] arr) { // Construction of large top reactor for (int i = arr.length / 2 - 1; i >= 0; i--) { // From the first non leaf node, from bottom to top, from left to right adjustHeap(arr, i, arr.length); } // Adjust structure + swap top and end elements int temp = 0; for (int i = arr.length - 1; i > 0; i--) { // exchange temp = arr[i]; arr[i] = arr[0]; arr[0] = temp; adjustHeap(arr, 0, i); } } /** * Adjust an array (binary tree) to a large top heap * Complete the adjustment of the tree with non leaf nodes corresponding to i into a large top heap * * @param arr Array to be adjusted * @param i Represents the index of non leaf nodes in the array * @param length Indicates how many elements are adjusted */ private static void adjustHeap(int arr[], int i, int length) { // Save current variable int temp = arr[i]; // Start to adjust that k is the left child of node i for (int k = i * 2 + 1; k < length; k = k * 2 + 1) { // If the value of the left child node is less than that of the right child node if (k + 1 < length && arr[k] < arr[k + 1]) { // Let k point to the right node k++; } // If the child node is larger than the parent node if (arr[k] > temp) { arr[i] = arr[k];// Assign a larger value to the current node i = k;// Let i point to k and continue the comparison } else { break; } } // When the for loop ends, the maximum value of the tree with i as the parent node has been adjusted arr[i] = temp;//Put the temp value in the adjusted position }
5. Bubble sorting
Basic idea - by comparing the values of adjacent elements from front to back in the sequence to be sorted, the reverse order found is exchanged, so as to move the larger elements from front to back to complete the sorting
public static void bubbleSort(int[] arr) { if (null == arr || arr.length < 2) { return; } int temp; int count = 0; for (int i = 0; i < arr.length - 1; i++) { for (int j = 0; j < arr.length - 1 - i; j++) { count++; if (arr[j] > arr[j + 1]) { temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } System.out.println("Compared" + count + "second"); }
Optimization: if there is no element exchange after a comparison, it indicates that the sequence is orderly and the cycle should be ended
public static void bubbleSort1(int[] arr) { if (null == arr || arr.length < 2) { return; } int temp; int count = 0; boolean flag = false; for (int i = 0; i < arr.length - 1; i++) { for (int j = 0; j < arr.length - 1 - i; j++) { count++; if (arr[j] > arr[j + 1]) { flag = true; temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } if (flag) { flag = false; } else { break; } } System.out.println("Compared" + count + "second"); }
6. Quick sort
Basic idea - it is an improvement of bubble sorting. The basic idea is: divide the data to be sorted into two independent parts through one-time sorting. All the data in one part is smaller than all the data in the other part, and then quickly sort the two parts of data according to this method. The whole sorting process can be carried out recursively, so as to turn the whole data into an ordered sequence
public static void quickSort(int[] arr, int left, int right) { int l = left; int r = right; int pivot = arr[(left + right) / 2]; int temp = 0; while (l < r) { // Find the element on the left that is greater than or equal to the central axis value while (arr[l] < pivot) { l++; } // Find the element on the right that is less than or equal to the central axis value while (arr[r] > pivot) { r--; } // It indicates that the left side is less than or equal to the central axis value, and the right side is greater than or equal to the central axis value if (l >= r) { break; } // exchange temp = arr[l]; arr[l] = arr[r]; arr[r] = temp; // If after exchange, arr[l] == pivot let r-- if (arr[l] == pivot) { r--; } // If after exchange, arr[r] == pivot let l++ if (arr[r] == pivot) { l++; } } if (l == r) { l++; r--; } // Left recursion if (left < r) { quickSort(arr, left, r); } // Recursive right if (l < right) { quickSort(arr, l, right); } }
7. Merge sort
Basic idea - merge sort is a sort method based on the idea of merging. The algorithm adopts the classical divide and conquer strategy (divide and conquer divides the problem into some small problems and then solves them recursively, while the conquer stage "fixes" the answers obtained in different stages, that is, divide and conquer).
// Opening + closing public static void mergeSort(int[] arr, int left, int right, int[] temp) { if (left < right) { int mid = (left + right) / 2; // Left recursion mergeSort(arr, left, mid, temp); // Recursive right mergeSort(arr, mid + 1, right, temp); merge(arr, left, mid, right, temp); } } /** * merge * * @param arr Array to be sorted * @param left Left ordered sequence initial index * @param mid Intermediate index * @param right Right index * @param temp Transit array */ public static void merge(int[] arr, int left, int mid, int right, int[] temp) { // Initialization i, the initial index of the left ordered sequence int i = left; // Initialization j, initial index of ordered sequence on the right int j = mid + 1; // Points to the current index of the temp array int t = 0; // 1. First fill the left and right (ordered) data into temp according to the rules to know the ordered sequence on the left and right // Until one side is handled while (i <= mid && j <= right) { // If the current element of the ordered sequence on the left is smaller than the element of the ordered sequence on the right // Copy the current element on the left to the temp array // Move back if (arr[i] < arr[j]) { temp[t] = arr[i]; t++; i++; } else { temp[t] = arr[j]; t++; j++; } } // 2. Fill all the remaining data into temp while (i <= mid) { temp[t] = arr[i]; i++; t++; } while (j <= right) { temp[t] = arr[j]; j++; t++; } // 3. Copy all elements in temp to arr // Not all elements are copied every time t = 0; int tempLeft = left; while (tempLeft <= right) { arr[tempLeft] = temp[t]; t++; tempLeft++; } }
8. Cardinality sort (bucket sort)
Basic idea - unify all values to be compared into the same digit length, and fill zero in front of the shorter digit. Then, start from the lowest order and sort once in turn. In this way, the sequence will become an ordered sequence from the lowest order to the highest order.
public static void radixSort(int[] arr) { // Get the maximum number of digits in the array int max = arr[0]; for (int i = 0; i < arr.length; i++) { if (arr[i] > max) { max = arr[i]; } } int maxLength = (max + "").length(); // Define a two-dimensional array, representing 10 buckets, and each bucket is a one-dimensional array int[][] bucket = new int[10][arr.length]; // Define a one-dimensional array to record how many data are put in the corresponding bucket int[] bucketElementCounts = new int[10]; for (int i = 0, n = 1; i < maxLength; i++, n *= 10) { for (int j = 0; j < arr.length; j++) { // Take out the bit value corresponding to each element and sort it int digitOfElement = arr[j] / n % 10; // Put it into the corresponding bucket bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j]; bucketElementCounts[digitOfElement]++; } // Traverse each bucket and put the elements in the bucket into the original array int index = 0; for (int k = 0; k < 10; k++) { // If there is data in the bucket, put it into the original array if (bucketElementCounts[k] > 0) { for (int l = 0; l < bucketElementCounts[k]; l++) { arr[index++] = bucket[k][l]; } } // Set the corresponding position of the count array to 0 bucketElementCounts[k] = 0; } } }