Algorithm-Quick Sort and quicksort
As the name implies, quick sorting is fast, and the time complexity is O (nlogn ). From this perspective, many sorting algorithms, such as Merge Sorting, heap sorting, and even Hill sorting, can achieve this speed, but quick sorting is more widely used, the default sorting method in STL is quick sorting. In addition, the idea of "Partition" has inspired many people. BelowIntroduction in non-descending orderDo not have a deeper understanding, just make a brief note for yourself.
1) Partition)
The Division idea is very simple, but very important and widely used. That is, to put an array to be sorted on the left with an element as the Key, which is smaller than the key; otherwise, put it on the right. The possible conditions are: 3, 1, 4, 2, 0, KEY = 5, 6, 9, 7, 8. You can select any Key value. A good key value is helpful for improving performance, but the method of selecting the optimal key value is itself a sort idea. Therefore, for sorting, the first element is generally used as the Key. The following is an implementation of the Partition code:
Note: Here end is the N-1 of the array length.
1 int partition(int arr[],int start,int end){ 2 int i=start, j=end, key; 3 if (start>=end) return -1; 4 for(key=arr[i]; i<j;){ 5 for(;i<j && arr[j]>=key; --j); 6 arr[i] = arr[j]; 7 for(;i<j && arr[i]<=key; ++i); 8 arr[j] = arr[i]; 9 }10 arr[i] = key;11 return i;12 }
First, define two subscript variables I and j, respectively pointing to the start and end, and use the element of start as the key value. Then, traverse arr [] From the back to the front, find the element j smaller than the key, and overwrite I; traverse arr [] From the back to the back, find the element I greater than the key, and overwrite j. Until I met j and wrote the key back to I. In this case, the position of I indicates the position where the selected key is located. That is, the element on the left of the key is not greater than the key, and the element on the right of the key is not less than the key. Returns the subscript position I of the key. The time complexity is O (n ).
2) quick sort)
Quick sorting is based on the Division idea. After each division, the key location (subscript) must be the location of the sorted key! 3, 1, 4, 2, 0, KEY = 5, 6, 9, 7, 8. Element 5 is in position 5 at this time, which is the position after sorting. Another example is: 3, 5, 1, KEY = 10, 23, 19. element 10 is in position 3, which is also the position after sorting. That is why quick sorting by division is possible.
The idea of quick sorting is: For the array arr [] and its first element position start and end element end, select one of the elements as the Key for a division, the position where the key should be located at this time. Then start ~ for the left part of the key ~ I-1, for the right part of the key I + 1 ~ End is used for Division. Gradually, a smaller range is used for Division. The sorting is complete. Logstores are divided into two parts each time, so the complexity of the fast sorting time is O (nlogn ).
void quick_sort(int arr[],int start, int end){ int mid; mid = partition(arr,start,end); if (mid<0) return; quick_sort(arr,0,mid-1); quick_sort(arr,mid+1,end);}
A more clever way of writing quick sorting, combining quick_sort with partition is as follows:
1 void quick_sort(int arr[],int start,int end){ 2 int i=start, j=end, key; 3 if (start>=end) return; 4 for(key=arr[i]; i<j;){ 5 for(;i<j && arr[j]>=key; --j); 6 arr[i] = arr[j]; 7 for(;i<j && arr[i]<=key; ++i); 8 arr[j] = arr[i]; 9 }10 arr[i] = key;11 quick_sort(arr,0,i-1);12 quick_sort(arr,i+1,end);13 }
Note: The above end is an array length N-1.
For arrays of N-length arr [], quick sorting only calls quick_sort (arr, 0, N-1 ).
3) Fast sorting of linked lists
There are also many sorting methods for linked lists. Here we use quick sorting to sort a single-chain table. The linked list node is defined as follows:
1 typedef struct _ListNode{2 int val;3 struct _ListNode *next;4 }ListNode;
When dividing an array, it takes a long time to move its elements. However, for a linked list, the elements do not need to be moved after partitioning. Instead, you only need to exchange pointers. Therefore, define two pointers, mid and p, and p, to perform fast backward traversal. When a node is smaller than the KEY, add it to the end of the mid and move one digit behind the mid. After a partition is executed, p reaches the position where the end is NULL and the mid is the KEY, and start ~ is further divided ~ Mid and mid ~ End. The Code is as follows:
1 void qsort(ListNode *start,ListNode *end){ 2 if (start==end || start==NULL) return; 3 ListNode *p,*mid; 4 for(p=mid=start; p!=end; p=p->next){ 5 if(p->val > start->val) continue; 6 mid = mid->next; 7 swap(p->val,mid->val); 8 } 9 swap(start->val,mid->val);10 qsort(start,mid);11 qsort(mid->next,end);12 }
For a ListNode * head single-chain table with no headers, you only need to call qsort (head, NULL); for fast sorting. The parition has been merged into the quick sorting, and the Partition is not provided separately. If necessary, write it out.