1. Concept
Quick sort, if you listen to the name, you can think that it has a faster sorting speed. It is a divide and conquer idea. Many sorting libraries that come with various languages now use quick sort.
space complexity
Quick sort is an in-situ sorting that only requires a small stack as an auxiliary space, and the space complexity is O(log 2 n), so it is suitable for use when the data set is relatively large.
time complexity
The time complexity is more complicated, the best case is O(n), and the worst case is O(n 2 ), so O(nlogn) is usually referred to as the average time complexity.
2. Basic idea
Randomly find a number, you can take it randomly, or you can take a fixed position. Generally, the first or last one is called the benchmark, and then the one smaller than the benchmark is placed on the left, and the one larger than the benchmark is placed on the right. How to do it, It is to exchange with the benchmark, so that after the exchange, the left side is smaller than the benchmark, and the right side is larger than the benchmark, so that an array is divided into two sub-arrays, and then the sub-array is divided into smaller ones according to the same method. subarrays until they cannot be decomposed.
3. Examples [1]
The method is actually very simple,
1. Start "probing" from both ends of the initial sequence "6 1 2 7 9 3 4 5 10 8" respectively. First find a number less than 6 from right to left, then find a number greater than 6 from left to right, and then swap them. Two variables i and j can be used here, pointing to the leftmost and rightmost of the sequence, respectively. We give these two variables nice names "sentry i" and "sentry j". At the beginning, let the sentinel i point to the leftmost of the sequence (ie i=1), pointing to the number 6. Let sentinel j point to the far right of the sequence (i.e. j=10), pointing to the number 8.
First sentinel j began to dispatch. Because the base number set here is the leftmost number, it is very important that sentinel j is dispatched first (please think about why). Sentinel j moves to the left step by step (i.e. j--) until it finds a number less than 6 and stops.
2. Next, the sentinel i moves to the right step by step (i.e. i++) until it finds a number greater than 6 and stops. Finally, sentinel j stopped in front of the number 5, and sentinel i stopped in front of the number 7.
Now swap the values of the elements pointed to by sentinel i and sentinel j. The sequence after the swap is as follows.
1 #Quick sort incoming list, start position and end position 2 def quick_sort( li , start , end ): 3 #If start and end meet, it means that there is only one number left in the sub-sequence I want to sort, so I don’t need it Sorted 4 if not start < end : 5 return 6 7 mid = li[start] #Take out the first number as the reference number mid 8 low = start # low to mark the left side from the reference number to find the one larger than mid Number position 9 high = end # high to mark the right end to the left to find the position of the number smaller than mid 10 11 #We want to loop, as long as low and high do not meet, and when low and high are equal, it means they meet 12 while low < high : 13 #Starting from high to the left, find the first number that is smaller than or equal to mid, mark the position, (if the number of high is larger than mid, we move high to the left) 14 #And we have to determine before finding, if low and high 15 while low < high and li[high] > mid : 16 high -= 1 17 #After jumping out of while , the subscript of high is the found number on the right side that is smaller than mid 18 #Find it Put the number in the left space low to mark this space 19 li[low] = li[high] 20 #Start from low to the right, find the first number larger than mid, mark the position, (if the number of low is less than Equal to mid, we move low to the right) 21 #And we have to make sure that before we find it, if low and high meet, we will not find it. 22 while low < high and li[low] <= mid : 23 low += 1 24 #After jumping out of the while loop, the subscript of low is the position of the number on the left that is larger than mid. 25 #We put the found number on the vacancy on the right, and high marks the vacancy 26 li[high] = li[low] 27 #Above we have finished finding a decimal from the right and moving to the left, finding a large number from the left and moving to the right 28 #When this while jumps out, it is equivalent to low and high meeting, we put the mid position Put it in this space 29 li[low] = mid 30 #At this time, the numbers on the left side of mid are smaller than mid, and the numbers on the right side of mid are 31 32 #Then we sort all the numbers on the left side of mid as above 33 quick_sort( li , start, low-1 ) 34 #We sort all numbers on the right side of mid as above 35 quick_sort( li , low +1 , end ) 36 37 38 # ok let's practice 39 if __name__ == ' __main__ ' : 40 li = [5,4,3,2,1 ] 41 quick_sort(li , 0 , len(li) -1 ) 42 print (li)
4. Algorithm Analysis
Advantages: fast speed, space left, disadvantages: very fragile, must pay attention to a few small details when implementing.
When is it best to:
The sequence to be sorted is sorted in ascending order O(n), that is, 1 2 3 4 5 6 7. In this case, the benchmark selects the first number and the number of adjustments is the least. Note that only the number of debugging is reduced, and the number of comparisons is not less.
So in theory, the comparison just needs to put the data into the register and then compare.
mov ax,
mov cx,
cmp ax,cx
But in reality, because of the existence of L1 and L2, and then your program has various complex factors such as process switching, on-site recovery, etc., the actual speed is easy to say.
What is the worst case:
The descending order of the sequence to be sorted is O(n 2 ), that is, 7 6 5 4 3 2 1, which degenerates into bubble sort.
5. Blind
Quick sort, after the first pass, the base number you choose is the real position of the number in the sorting sequence.
So you can think about it, if the benchmark is chosen accurately, can the median of a series be quickly found? ? ?