The sorting summary algorithm is a substantially and commonly used algorithm. Since the number of treated in the actual work is huge, the sorting algorithm has a high speed of the algorithm itself. And the performance of our so-called algorithm is mainly the complexity of the algorithm, generally expressed in an O method. I will give a detailed description later.
For sorting algorithms, I want to do a simple introduction first, and give this article an outline. I will analyze the algorithm from simple to difficulty in accordance with the complexity of the algorithm. The first part is a simple sort algorithm, and later you will see their common point is O (n * n) (because Word did not use Word, so it could not be played. The second part is the advanced sort algorithm, complexity is O (log2 (n)). Here we only introduce one algorithm. There are also several algorithms that are not discussed here because they involve the concept of trees and piles. The third part is similar to the brain. The two algorithms here are not the best (even with the slowest), but the algorithm itself is quite, worth reference (programming angle). At the same time, we can let us know this issue from another perspective. The fourth part is a meal after I gave you a meal - a template-based universal rapid sort. Since the template function can be sorted for any data type (sorry, some forum experts are used). Now let's get started: First, the simple sorting algorithm is simple because the program is relatively simple, so there is no comment. All procedures give full running code and run through my VC environment. Since there is no content involving MFC and Windows, there should be no problem on the platform of Borland C . After the code is given, the running process is given, I hope to help understand.
1. Adventure: This is the most primitive, and it is also the slowest algorithm that is well known. The origin of his name is bubbling because of its work. #Include
Void Bubblesort (INT * PDATA, INT Count) {ITEMP; For (INT i = 1; i
Void main () {int Data [] = {10, 9, 8, 7, 6, 5, 4}; bubblesort (data, 7); for (int i = 0; i <7; i ) cout << Data [i] << ""; cout << "/ n";}
Reverse (worst) first round: 10, 9, 8, 7-> 10, 9, 7, 8-> 10, 7, 9, 8-> 7, 10, 9, 8 (exchange 3 times) Two rounds: 7, 10, 9, 8-> 7, 10, 8, 9-> 7, 8, 10, 9 (exchange 2 times) first round: 7, 8, 10, 9-> 7, 8, 9, 10 (exchange 1 time) cycle number: 6 exchanges: 6 times
Other: First round: 8, 10, 7, 9-> 8, 10, 7, 9-> 8, 7, 10, 9-> 7, 8, 10, 9 (exchange 2 times) second round: 7 8, 10, 9-> 7, 8, 10, 9-> 7, 8, 10, 9 (exchanging 0 times) first round: 7, 8, 10, 9-> 7, 8, 9, 10 Exchange 1 time: 6 exchanges: 3 times, we give the block, now we analyze it: Here, the main part of the performance of our algorithm is cycle and exchange, obviously, the number of times, the performance is more difference. From the above program we can see that the number of cycles is fixed, 1 2 ... N-1. The formula is 1/2 * (n-1) * n. Note now, we give a definition of the O method:
If there is a constant K and the starting point N0, when n> = N0, F (n) <= k * g (n) is present, then f (n) = O (g (n)). (Oh, don't say that you have not learned mathematics, it is very important for programming mathematics !!!)
Now let's see 1/2 * (n-1) * n, when K = 1/2, N0 = 1, g (n) = n * n, 1/2 * (n-1) * n <= 1/2 * n * n = k * g (n). Therefore, F (n) = O (g (n)) = O (n * n). Therefore, our program cycle has an complexity of o (n * n). Look at the exchange. The table followed by the program can be seen, the cycles of the two cases are the same, and the exchange is different. In fact, the exchange itself has a great relationship with the order of data sources. When the data is in reverse, the number of exchanges is the same as the cycle (each cycle is judged), the complexity is O (N * n). When data is a positive order, there will be no exchange. The complexity is O (0). In the middle of the chart. It is because of this reason, we usually compare the algorithm through the number of cycles.
2. Exchange method: The program of the exchange method is the clearest and simple, and each time you use the current element to compare and exchange it. #include Void main () {int data [= {10, 9, 8, 7, 6, 5, 4}; ExchangeEsort (Data, 7); for (int i = 0; i <7; i ) cout << Data [i] << "; cout <<" / n ";} Reverse (worst) first round: 10, 9, 8, 7-> 9, 10, 8, 7-> 8, 10, 9 , 7-> 7, 10, 9, 8 (exchange 3 times) second round: 7, 10, 9, 8-> 7, 9, 10, 8-> 7, 8, 10, 9 (exchange 2 times) The first round: 7, 8, 10, 9-> 7, 8, 9, 10 (exchange 1 time) cycle number: 6 times exchange: 6 times, 1: First round: 8, 10, 7, 9-> 8, 10, 7, 9-> 7, 10, 8, 9-> 7, 10, 8, 9 (exchanging 1 time) second round: 7, 10, 8, 9-> 7, 8, 10, 9 -> 7, 8, 10, 9 (exchange 1) First round: 7, 8, 10, 9-> 7, 8, 9, 10 (exchange 1 time) cycle number: 6 times exchange: 3 times From the work-run table, exchange is almost as bad as the bubble. The fact is indeed true. The number of cycles and the bubbling is also 1/2 * (n-1) * n, so the complexity of the algorithm is still O (n * n). Since we can't give all the circumstances, they can only tell you that they are also the same as they are in exchange (slightly better in some cases, slightly poor in some cases). 3. Select method: Now we can finally see a point of hope: the choice method, this method improves a little performance (in some cases) This method is similar to our artificial sorting habits: the minimum of the same is selected from the data. Value exchange, select the smallest and second exchange in the section below, so that it is recovered. #include Void main () {int Data [] = {10, 9, 8, 7, 6, 5, 4}; selectsort (data, 7); for (int i = 0; i <7; i ) cout << Data [i] << "; cout <<" / n ";} Reverse (worst) first round: 10, 9, 8, 7-> (itemp = 9) 10, 9, 8, 7-> (itemp = 8) 10, 9, 8, 7-> (itemp = 7) 7, 9, 8, 10 (exchange 1 time) second round: 7, 9, 8, 10-> 7, 9, 8, 10 (itemp = 8) -> (itemp = 8) 7, 8, 9, 10 (exchanging 1 time) first round: 7, 8, 9, 10 -> (itemp = 9) 7, 8, 9, 10 (Exchange 0 times) Cycle number: 6 times Exchange: 2 times Other: First Wheel: 8, 10, 7,9 -> (itemp = 8) 8, 10, 7,9 -> (itemp = 7) 8 , 10, 7, 9 -> (itemp = 7) 7, 10, 8, 9 (exchange 1 time) second round: 7, 10, 8, 9 -> (itemp = 8) 7, 10, 8, 9 -> (itemp = 8) 7, 8, 10, 9 (exchange 1 time) first round: 7, 8, 10, 9 -> (itemp = 9) 7, 8, 9, 10 (exchange 1 time) cycle Number of exchanges: 6 exchanges: 3 regrets is that the number of cycles required by the algorithm is still 1/2 * (n-1) * n. Therefore, the algorithm complexity is O (n * n). Let's see his exchange. Since each outer cycle only generates a exchange (only one minimum). So f (n) <= n, so we have F (n) = O (n). Therefore, when the data is chaotic, it can reduce a certain number of exchanges. 4. Insert method: Inserting method is more complicated, its basic working principle is to draw a card, looking for the corresponding position in the previous card, then continue next #include Void main () {int Data [] = {10, 9, 8, 7, 6, 5, 4}; insertsort (data, 7); for (int i = 0; i <7; i ) cout << Data [i] << ""; cout << "/ n";} Reverse (worst) first round: 10, 9, 8, 7-> 9, 10, 8, 7 (exchange 1 time) (cycle 1 time) second round: 9, 10, 8, 7-> 8 , 9, 10, 7 (exchange 1) (2 times) first round: 8, 9, 10, 7-> 7, 8, 9, 10 (exchange 1 time) (cycle 3 times) cycle number: 6 Supreme exchange: 3 times Others: First round: 8, 10, 7, 9-> 8, 10, 7, 9 (exchange 0 times) (cycle 1 time) second round: 8, 10, 7, 9-> 7, 8, 10 , 9 (exchange 1 time) (2 times) first round: 7, 8, 10, 9-> 7, 8, 9, 10 (exchange 1 time) (cycle 1 time) cycle number: 4 times exchange: The behavior analysis ended above is in fact caused a description, let us think this algorithm is the best in the simple algorithm, in fact, because the number of cycles is not fixed, we can still use the O method. As can be seen from the above results, the number of cycles f (n) <= 1/2 * n * (N-1) <= 1/2 * n * n. Therefore, its complexity is still o (n * n) (hereinafter explained, in fact, if it is not to show these simple sorting, the number of exchanges can still be derived). Now, in exchange, look at the appearance, the number of exchanges is O (n) (derive similar selection method), but we have to perform the same number of in the inner layer loop each time. Normal exchange we need three times '=' and there is more than one here, so we waste time. In the end, I personally think that in the simple sort algorithm, the choice method is best. Second, advanced sorting algorithm: In the advanced sorting algorithm, we will only introduce this, and it is the fastest in my current (I have seen). Its work looks still like a binary tree. First we select a middle value middle program we use the intermediate value of the array, then put it smaller than it on the left, big placed on the right (the specific implementation is from both sides, find a pair of posts). Then use this process (the easiest way - recursive) on both sides. 1. Quick sort: #include Void Run (int * PDATA, INT LEFT, INT RIGHT) {INT I, J; INT MIDDLE, ITEMP; I = Left; J = Right; Middle = PDATA [(Left Right) / 2]; // Seeking intermediate value Do {While ((PDATA [i] // When the left part is value (Left Void Quicksort (INT * PDATA, INT Count) {Run (PDATA, 0, Count-1); Void main () {int Data [] = {10, 9, 8, 7, 6, 5, 4}; Quicksort (Data, 7); for (int i = 0; i <7; i ) cout << Data [i] << ""; cout << "/ n";} Here I have no analysis of behavior, because this is very simple, we directly analyze the algorithm: First we consider the most ideal case 1. The size of the array is 2 power, so that it can always be divided by 2. Assume that K = log2 (n) is assumed to be 2. 2. Each time we have selected is just an intermediate value, so that the array can be aliquoted. The first layer recursive, circulating N times, the second layer cycle 2 * (N / 2) ... So a total of N 2 (N / 2) 4 (N / 4) N * (n / n) = n n n ... n = k * n = log2 (n) * n, algorithm complexity is O (log2 (n) * n) other case only than this situation Poor, the worst case is that each selected Middle is a minimum or maximum, then he will turn into an exchange method (due to the use of recursive, the situation is worse). But how big is you think of this situation? ? Oh, you don't have to worry about this problem. Practice has proved that most cases, rapid sorting is always best. If you are worried about this problem, you can use a heap sort, which is a stable O (log2 (n) * n) algorithm, but usually the speed is slower than fast sorting (because of the restructuring stack). Third, other sort 1. Bidirectional bubble: The usual bubble is unidirectional, and here is two-way, that is to say, it is necessary to perform reverse work. The code looks complicated. If you care about it, it is a way to go back and forth. The author writes this code believes that this can reduce some exchanges on the basis of the bubble (I don't think so, maybe I am wrong). Anyway, I think this is a fun code, it is worth seeing. #include // Reverse part for (i = Left; i 2. SHELL Sorting this sort is very complicated, and I will know the program. First, a decreasing step is required, where we use 9, 5, 3, 1 (the last step must be 1). The working principle is first sorted by all of the contents of 9-1 elements, and then use the same method to sequencing the sequencing of the 5-1 elements separated by the same method. #include INT ITEMP; INT K, S, W; For (int i = 0; i <4; i ) {k = step [i]; s = -k; for (int J = k; j Void main () {int Data [= {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, -10, -1}; shellsort (data, 12); for (int i = 0; I <12; i ) cout << Data [i] << ""; cout << "/ n";} Oh, the program seems to have some headache. However, it is not very difficult, and it is easy to remove the blocks of s == 0. Here is the code to avoid using 0 steps to cause an exception. I think it is worth seeing this code. This algorithm is named because the name of the inventors D.L.Shell. According to the reference: "Because of the complex mathematical reasons, it avoids the use of 2 power secondary steps, it can reduce the efficiency of algorithm." The complexity of the algorithm is 1.2 power of N. Due to the fact that it is very complex and "exceeding the discussion of this book" (I don't know the process), we only have the results, the template-based general sort: I want to have no analysis, you can see it. . I don't understand, I can ask in the forum. MYDATA.H file /// Class CMYDATA {Public: CMYDATA (int index, char * strdata); cmydata (); virtual ~ cmydata (); INT M_IINDEX; INT getDataSize () {return m_idatasize;}; const char * getdata () {return m_strdatamember;}; // Here, Operators: CMYDATA & OPERATOR = (CMYDATA & SRCDATA); BOOL Operator <(CMYDATA & DATA); BOOL Operator> (CMYDATA & DATA); Private: char * m_strdatamember; int m_idatasize;}; MyData.cpp file CMYDATA :: CMYDATA (): m_iindex (0), m_idatasize (0), M_StrDataMember (null) {} CMYDATA: :: ~ CMYDATA () {if (m_strdatamember! = Null) delete [] m_strdatamember; m_strdatamember = null;} CMyData :: CMyData (int Index, char * strData): m_iIndex (Index), m_iDataSize (0), m_strDatamember (NULL) {m_iDataSize = strlen (strData); m_strDatamember = new char [m_iDataSize 1]; strcpy (m_strDatamember, strData } CMyData & CMyData :: operator = (CMyData & SrcData) {m_iIndex = SrcData.m_iIndex; m_iDataSize = SrcData.GetDataSize (); m_strDatamember = new char [m_iDataSize 1]; strcpy (m_strDatamember, SrcData.GetData ()); return * this; } Bool CMYDATA :: Operator <(CMYDATA & DATA) {Return M_IINDEX Bool CMYDATA :: Operator> (CMYDATA & DATA) {Return M_IINDEX> DATA.M_IINDEX;} /// /// Main program part #include Template // When the left part is value (Left Template Void main () {CMYDATA DATA [] = {CMYDATA (8, "Xulion"), CMYDATA (7, "Sanzoo"), CMYDATA (6, "Wangjun"), CMYDATA (5, "VCKBASE"), CMYDATA (4 , "Jacky2000", CMYDATA (3, "CWALLY"), CMYDATA (2, "VCUSER"), CMYDATA (1, "ISDONG")}; Quicksort (Data, 8); for (int i = 0; i < 8; i ) cout << Data [i] .m_iindex << "<<" data [i] .Getdata () << "/ n"; cout << "/ n";} Transfer from: Jerry's Irrigation Park