Quick Sort (C language)-parsing

Source: Internet
Author: User

Quick Sort

The fast sort is a sort algorithm, and the worst-case run time is O (N2) for an input array containing n numbers. Although this worst-case run time is poor, fast sequencing is often the best practical choice for sorting,

This is because the average performance is quite good: the expected run time is O (NLGN), and the O (NLGN) notation has a small implied constant factor. In addition, it can be ordered in-place, and can work well in a virtual storage environment.

Quick Sort (Quicksort) is an improvement to the bubbling sort.
Quick Sort by C. A. R. Hoare was introduced in 1962. Its basic idea is: by a trip to sort the data to be sorted into two separate parts, one part of all the data is smaller than the other part of all the data, and then the two parts of the data are quickly sorted by this method, the entire sorting process can be recursive, so as to achieve the entire data into an ordered sequence.
Like a merge sort, the quick sort is also a split-rule model. The following is a three-step process for sorting a typical array A[P......R]: decomposition:

Array A[P......R] is divided into two (possibly empty) sub-arrays a[p......q-1] and A[Q+1......R], so that each element in a[p......q-1] is less than or equal to a (q), and less than or equal to the elements in A[Q+1......R]. The small Mark Q is also calculated during this partitioning process.

Solve:

Sort by recursive invocation of quick sort, for arrays a[p......q-1] and A[Q+1......R].

Merge:

Since two sub-arrays are sorted in place, merging them does not require an operation: the entire array A[P......R] is sorted.

The following procedure implements a quick sort (pseudo-code):

QUICK SORT (A,P,R)

1  if p<r2         then  q<-PARTITION (a,p,r)3             QUICKSORT (A , p,q-1)4             QUICKSORT (a,q+1, R)

To sort a complete array A, the initial call is Quicksort (A,1,length[a]).

Array partitioning:

The key to the fast sorting algorithm is the partition process, which is a sub-array A[P......R] in-place reflow (pseudo code):

PARTITION (A,p,r)

 1  x <- A[r]  2  i <-p-1  3  for  J <-p to R-1  4  do  if  a[j]<=x  5  the n i <-i+1  6  Exchange A[i ] <-> A[j]  7  Exchange A[i + 1 ] <-> A[j]  8  return  i+1  
The Sort demo example assumes that the user has entered the following array:
Subscript 0 1 2 3 4 5
Data 6 2 7 3 8 9
Create a variable i=0 (point to the first data), j=5 (point to the last data), k=6 (assigns the value of the first data). We're going to move all the numbers smaller than K to the left of K, so we can start looking for a smaller number than 6, starting with J, from right to left, constantly diminishing the value of the variable J, we find the first subscript 3 of the data is smaller than 6, so the data 3 is moved to subscript 0 position, the subscript 0 of the data 6 to subscript 3, the first comparison is completed:
Subscript 0 1 2 3 4 5
Data 3 2 7 6 8 9
I=0 j=3 K=6 Then, to start the second comparison, this time to become a bigger than the K, and to go after the search. Sliding scale variable I, found that the data of subscript 2 is the first larger than the K, so with the subscript 2 of the data 7 and J points to the subscript 3 of the data of 6 to exchange, the data state into the following table:
Subscript 0 1 2 3 4 5
Data 3 2 6 7 8 9
                  i=2 j=3 K=6 says the above two comparisons are a cycle.   Then, the variable j is then decremented, repeating the above cycle comparison. In this example, we do a loop and find I and J "Meet": they all point to subscript 2. So, the first time the comparison is over. The results are as follows, usually K (=6) the number on the left is smaller than it, the number of K right is larger than it:
Subscript 0 1 2 3 4 5
Data 3 2 6 7 8 9
If I and J do not meet, then sliding scale I find large, not yet, and then diminishing J to find small, so repeated, continuous circulation.  Attention to judgment and search is carried out at the same time. Then, the data on both sides of the K, and then the process is divided into the above, until no further grouping.
Note: The first time quick sort does not directly get the final result, only the number smaller than K and K is divided into the two sides of K. To get the final result, you need to perform this step again on an array of subscript 22 edges, and then decompose the array until the array is no longer decomposed (only one data) to get the correct result.

1) Set two variables I, J, at the beginning of the order: i=0,j=n-1;2) with the first array element as the key data, assign the value to key, i.e. key=a[0];3) Forward search from J, that is, after starting the forward search (j--), find the first value less than key A[j], will a[j] and A[i] interchange;4) Backward search from I, that is, start backward search (i++), find the first a[i] greater than key], interchange a[i] and a[j];5) Repeat 3rd, 4, until i=j, (3,4 step, did not find the qualifying value, that is, 3 a[j] is not less than the key,4 A[i] is not larger than the time to change the value of J, I, so j=j-1,i=i+1, until found. Locate the value that matches the condition, and the J pointer position does not change when I exchange it. In addition, I==J this process must be exactly when the i+ or J completes, at which time the loop ends).  code (C language):
1#include <stdio.h>2 3 4 voidQuick_sort (int*a,intLeftintRight//Method5 {6     if(left >= right)/*if the index on the left is greater than or equal to the right, it means that a group has been collated.*/7         return ;8     inti =Left ;9     intj =Right ;Ten     intKey =A[left]; One      while(I < J)/*control in a group to look for again*/ A     { -          while(I < J && Key <=A[j]) -         /*and looking for the end of the condition is, 1, find a number greater than key (greater than or less than depending on what you want to ascend the order or Descending, here is ascending) 2, not match the condition 1, and I and J size no reversal*/  -         { -j--; -         } +A[i] =A[j]; -          while(I < J && Key >=A[i]) +         /*This is I in the group to look forward, ibid, but note the size relationship with the key stop cycle and the opposite, A because the idea of sorting is to throw a number on both sides, the number of left and right sides is the opposite of key.*/ at         { -i++; -         } -A[J] =A[i];  -     } -A[i] = key;/*return the median key when you've finished searching within the group*/ inQuick_sort (A, left, I-1);/*Finally, the same approach to the left side of the group*/ -Quick_sort (A, i +1, right);/*use the same approach to the group on the right*/ to }  + intMain () - { the     inta[Ten]; *     inti,j,t; $printf"input numbers: \ n");//inputPanax Notoginseng      for(i =0; I <Ten; i++)//Array -scanf"%d", &a[i]);//A[0]~a[9] theprintf"\ n"); +     voidQuick_sort (int*a,intLeftintRight ); AQuick_sort (A,0,9);  theprintf"The sorted numbers: \ n"); +      for(i =0; I <Ten; i++)//Output -printf"%d", A[i]);//Array $printf"\ n");  $     return 0; -}

Input/output:

History:

The quick sort was proposed by C. A. R. Hoare(Donnijol, Charles Antony Richard Hoare) in 1960, after which many further optimizations were made. If you are interested in a quick sort, you can look at the paper "Quicksort" published by Donnijol in Computer Journal in 1962 and the seventh chapter of the Introduction to Algorithms . The fast sorting algorithm was only the first exposure of Donnijol in the computer field, and later he was appreciated and reused by the boss, who wanted to design a new high-level language for the new machine. You should know that there is no such thing as Pascal or C language. Later Donnijol took part in the "ALGOL 60" training course, held by Edsger Wybe Dijkstra (1972 Turing Award winner, the Great God we will meet later), and he felt that he was not so sure of designing a new language as to the existing "ALGOL 60 "To be improved so that it can be used on the company's new machine. So he designed a subset version of "ALGOL 60". This version of the implementation of efficiency and reliability in the then "ALGOL 60" of the various versions of the top, so Donnijol by the international academic attention. Later, he also invented the familiar "case" statement in the "ALGOL X" design, which was later widely used in a variety of high-level languages, such as Pascal, C, the Java language, and so on. Of course, Donnijol has a lot of contributions to the computer field, and he won the Turing Award in 1980.

Optimization:
three-mean partitioning method
The simplest description of this improvement is probably this: unlike the general quick Sort method, it does not select the first number of arrays to be ranked as the middle axis, but instead chooses the middle of the leftmost, rightmost, and most intermediate three elements of the array to be sorted. This improvement has a two-point advantage over the original fast-sorting algorithm:
(1) First, it reduces the chance of worst-case occurrence.
(2) Secondly, there is no improved fast sorting algorithm in order to prevent the comparison when the array out of bounds, at the end to set a sentinel point. The improvement based on the partition sizing algorithm is for the weaknesses of the fast sorting algorithm. Fast sorting is not good for small-scale data set performance. Some may think that this shortcoming can be overlooked, because most of the sorting takes into account the large-scale adaptability on the line. But the fast sorting algorithm uses the divide-and-conquer technique, in the end, the large data sets are divided into small data sets for processing. The improved result is that, when the dataset is small, you do not have to continue to call the fast sort algorithm recursively, but instead call other sorting algorithms that are more capable of processing small datasets. Introsort is such an algorithm, it began to use a fast sorting algorithm to sort, when the recursion reached a certain depth to the heap sorting to deal with. This overcomes the complex mid-axis selection of the fast sort in small-scale data set processing, and also ensures that heap sequencing is in the worst case o (n log n) complexity.
Another optimization improvement is to stop the fast sorting algorithm when the size of the partition reaches a certain hour. The final product of the fast sorting algorithm is an ordered sequence of "almost" sort completion. There are some elements in the sequence that do not go to the final ordered sequence, but this is not a lot of elements. This sort of "almost" finished sequence can be sorted by using the Insert sort algorithm to finalize the entire sorting process. Because the insertion sort has a near-linear complexity for this "almost" completed sort sequence. This improvement proves to be much more effective than the continuous use of fast sorting algorithms.
Another improved strategy for quick sorting is to prioritize the smallest partition when recursively sorting sub-partitions. This option makes it possible to use storage space more efficiently to accelerate the implementation of the algorithm as a whole. Different partitioning schemes consider that for a fast sorting algorithm, a large amount of time is actually spent on partitions, so a good partitioning implementation is very important. In particular, when all the element values of the partition are equal, the general fast sort algorithm falls into the worst case, exchanging the same elements repeatedly and returning the worst mid-axis values. Any data set, as long as they contain many of the same elements, is a serious problem because many of the "bottom-up" partitions will become exactly the same.
An improved way to do this is to divide the partition into three blocks instead of the original two: a piece is any element that is less than the middle axis value, a piece is equal to all the elements of the middle axis value, and the other is all elements larger than the middle axis value. Another simple improvement is to avoid recursive calls and other sorting algorithms when the partition is complete and if the values of the left and right two elements are found to be equal. Parallel fast sequencing because the fast sorting algorithm is implemented by using divide-and-conquer technology, it is easy to be processed in parallel on multiple processing machines.
In most cases, the time required to create a thread is much greater than the time it takes to compare and exchange two elements, so a fast-sorting parallel algorithm cannot create a new thread for each partition. In general, a threshold is set in the implementation code, and if the number of elements in the partition is greater than the threshold, a new thread is created to handle the sorting of the partition, otherwise recursive ordering is used.
There are also improvements to this parallel fast sorting algorithm. The main problem with this algorithm is that this step of partitioning is always done before the sub-sequence is processed in parallel, which limits the degree of parallelism of the entire algorithm. The workaround is to also process the partitioning step in parallel. The improved parallel fast sorting algorithm uses 2n pointers to process partitioning in parallel, increasing the degree of parallelism of the algorithm.

Variants
randomize Fast Rows
The worst case for a quick sort is based on the selection of the main element for each partition. A basic quick sort selects the first element as the primary entity. This gives the worst results for each partition when the array is already in order. A more common optimization method is the stochastic algorithm, that is, random selection of an element as the main element. In this case, although the worst case is still O (n^2), the worst case is no longer dependent on the input data, but on the poor value of the random function. In fact, the probability of a stochastic quick ordering to get a theoretical worst case is only 1/(2^n). So randomization fast sequencing can achieve the desired time complexity of O (NLOGN) for the vast majority of input data. A predecessor made a brilliant summary: "Random rapid sequencing can meet a person's lifelong personality needs." "The only downside to randomization is that once there's a lot of the same data in the input data, the randomization effect will be reduced directly." For the limit case, that is, for n the same number of orders, the time complexity of the randomization fast sequencing will undoubtedly be reduced to O (n^2). The workaround is to scan in a way that allows the primary element to remain in place without an interchange.   Balance the fast row whenever possible, select an element that represents the median value as the key data, and then follow the principle of normal fast-running for comparison, substitution, and recursion. In general, the method of selecting this data is to take the beginning, the end, the middle 3 data, by comparison to select the median. The advantage of taking these 3 values is that in real-world problems, the probability of an approximate sequential or reverse-order data is large, when the intermediate data is necessarily the median, and the de facto approximate median value. In case of a small (or vice-versa) in the middle of the data, take the value is close to the maximum, then because at least two parts can be separated, the actual efficiency will be about twice times the increase, but also conducive to the data slightly disrupted, destruction of degraded structure.   External Quick Row Unlike normal fast, the key data is a buffer that first reads the previous and subsequent M/2 elements into buffer and sorts the elements in the buffer, then reads the next element from the beginning (or end) of the sorted array, If this element is smaller than the smallest element in the buffer, write it to the first vacancy, and if the element is greater than the largest element in the buffer, write to the last empty space, otherwise write the largest or smallest element in the buffer to the array and place the element in buffer. Keep the maximum value below these critical data, and the minimum value is higher than the key data to avoid rearrangement of the intermediate data that is already ordered. When finished, the middle space of the array is inevitably vacated, and the buffer is written to the middle slot in the array. Then recursively to the outside of the smaller parts, the other parts of the loop to sort.   Three-way base fast row (Three-way Radix Quicksort, also known as Multikey Quicksort, MUlti-key Quicksort): The combination of the cardinal sort (radix sort, such as the general string comparison sort is the cardinal sort) and the characteristics of the fast row, is the more efficient algorithm in string sorting. The algorithm is sorted by an array of elements that have a feature, namely Multikey, such as a string, where each letter can be viewed as a key. Each time the algorithm selects an element in the sorted array as the key data, the first key (the letter) of the element is taken into account, and the other elements are divided into three parts less than, equal to, and greater than the key data by comparing the key. The "less than" and "greater than" sections are then recursively sorted based on the key position, and the "equals" section is sorted based on the next key.

Quick Sort (C language)-parsing

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.