Quick sort
basic thought
1. Find a benchmark number at random
2. Put all numbers less than him on the left and all large numbers on the right
3. Finally, repeat the above operations until the left and right pointers of each part meet
As shown in GIF, an unordered array 3 5 8 1 2 9 4 7 6
Take the right endpoint as the reference number, and then the left pointer starts scanning from the left. When it encounters a number > = 6, it stops. At this time, the right pointer starts scanning. When it encounters a number < = 6, it stops. The positions of the two numbers do not conform to the second basic idea, so it is exchanged. Then the left pointer starts scanning again. When the left and right pointers meet, it is the first traversal
The array is divided into two parts and the above operation is repeated
code
int op[10010];//Open array space void quick_sort(int op[], int l, int r) { if (l >= r)//End flag of recursion return ; int key = op[(l + r) / 2];//Reference number int i = l - 1, j = r + 1;//Left and right pointers (why - 1 and + 1) while (i < j) { do i++; while (op[i] < key);//Left pointer scan do j--; while (op[j] > key);//Right pointer scan if (i < j) {//Digital switching int t = op[i]; op[i] = op[j]; op[j] = t; } } quick_sort(op, l, j);//recursion quick_sort(op, j + 1, r); } int main() { int n; scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", &op[i]); quick_sort(op, 0, n - 1); for (int i = 0; i < n; i++) printf("%d ", op[i]); return 0; }
Time complexity
The time complexity of quick sort is O(nlogn)
Borrow here Spy ion Explanation of
Quick sort divides the array interval into two parts each time. In the most ideal case, that is, the selected benchmark number is exactly the median of this interval, then each segmentation can be divided into two intervals of the same size, and then recursion
- In the first layer of recursion, n numbers are divided into 2 intervals, and each interval has n/2 numbers
- In the second layer of recursion, n numbers are divided into 4 intervals, and each interval has n/4 numbers
- In the third layer of recursion, n numbers are divided into 8 intervals, and each interval has n/8 numbers
......... - In the log n layer of recursion, n numbers are divided into n intervals with 1 number in each interval
A total of logn level recursions are performed, and each recursion is O(n), so the time complexity of fast sorting is O(nlogn). However, when the array itself is an ordered sequence, the time complexity immediately becomes O(n^2), so fast sorting is unstable
matters needing attention
-
Why + 1, - 1?
-
Why do; while; Instead of while
-
Why use the middle value of the array as the benchmark instead of the endpoint
-
Why check the relative position of the pointer before switching
1. Question 1 and question 2 are the same question. This is because in order to prevent that the values of the numbers i and j are equal, and the numbers i and j are still equal after the exchange, resulting in program crash, you have to add and subtract each time2. Question 3 is the same as question 4. Taking the intermediate value as the benchmark is to prevent boundary problems
When you select the left endpoint as the benchmark, quick_sort(op, l, j),quick_sort(op, j + 1, r); Recursion here cannot take i as the boundary of recursion
Accordingly, when selecting the right endpoint as the benchmark, j cannot be used as the recursive boundary
It is because there will be unilateral dead circulation, such as 2 1 3 5 4
Template question
Merge sort
basic thought
1. The interval to be sorted is infinitely divided into indivisible sub intervals
2. Then merge all sub intervals in pairs, and complete the sorting operation in the merging process. Finally, the merged new areas are ordered sequences
Compared with fast scheduling, merge scheduling does not have so many boundary problems, and it is very simple. Moreover, the time complexity is O(nlogn), and there will be no situation with the most O(n^2) as fast scheduling
code
#include <stdio.h> int op[10010]; int temp[10010]; void merge_sort(int op[], int l, int r) { if (l >= r) return ; int mid = (l + r ) / 2; merge_sort(op, l, mid), merge_sort(op, mid + 1, r);//Recursive first int k = 0, i = l, j = mid + 1; while (i <= mid && j <= r) {//Post sort if (op[i] <= op[j]) temp[k++] = op[i++]; else temp[k++] = op[j++]; } while (i <= mid)//Add extra numbers to the array temp[k++] = op[i++]; while (j <= r) temp[k++] = op[j++]; for (i = l, j = 0; i <= r; i++, j++) op[i] = temp[j]; } int main() { int n; scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", &op[i]); merge_sort(op, 0, n - 1); for (int i = 0; i < n; i++) printf("%d ", op[i]); return 0; }
Time complexity
- In the first layer of recursion, n numbers are divided into 2 intervals, and each interval has n/2 numbers
- In the second layer of recursion, n numbers are divided into 4 intervals, and each interval has n/4 numbers
- In the third layer of recursion, n numbers are divided into 8 intervals, and each interval has n/8 numbers
......... - In the log n layer of recursion, n numbers are divided into n intervals with 1 number in each interval
A total of logn level recursions are performed, and each recursion is O(n), so the time complexity of merging and sorting is O(nlogn)