C ++ basic algorithm bubble method, exchange method, selection method, and implementation code set

Source: Internet
Author: User

1. Bubble Method:

This is the most primitive and well-known slowest algorithm.
The origin of his name is because its work seems to be bubbling:

Copy codeThe Code is as follows: # include <iostream. h>
Void BubbleSort (int * pData, int Count)
{
Int iTemp;
For (int I = 1; I <Count; I ++ ){
For (int j = Count-1; j> = I; j --){
If (pData [j] <pData [J-1]) {
ITemp = pData [J-1];
PData [J-1] = pData [j];
PData [j] = iTemp;
}
}
}
}
Void main (){
Int data [] = {10, 9, 8, 7, 6, 5, 4 };
BubbleSort (data, 7 );
For (int I = 0; I <7; I ++)
Cout <data <"";
Cout <"\ n ";
}

Reverse Order (worst case)
First round: 10, 9, 8, 7-> 10, 9, 7-> 10, 7, 9-> 7, 10, 9, 8 (three exchanges)
Round 2: 7, 10, 9-> 7, 10, 8-> 7, 8, 9 (2 exchanges)
First round: 7, 8, 10, 9-> 7, 8, 9, 10 (switching once)
Cycles: 6 exchanges: 6
Others: First Round:,->, 9-> (exchange twice)
Round 2: 7, 8, 10, 9-> 7, 8, 10, 9-> 7, 8, 10, 9 (0 exchanges)
First round:,->, 9, 10 (switching once) cycles: 6 exchanges: 3 above we provide the program segment,
Now let's analyze it: here, the main part that affects our algorithm performance is loop and exchange. Obviously, the more times, the worse the performance.
From the above program, we can see that the number of cycles is fixed, which is 1 + 2 +... + n-1. The formula is 1/2 * (n-1) * n.
Now note that we define the O Method: if there is a constant K and the starting point n0, f (n) exists when n> = n0) <= K * g (n), f (n) = O (g (n )).
Now let's look at 1/2 * (n-1) * n. When K = 1/2, n0 = 1, g (n) = n * n, 1/2 * (n-1) * n <= 1/2 * n = K * g (n ). So f (n) = O (g (n) = O (n * n ).
So the complexity of our program loop is O (n * n ). Let's look at the exchange. We can see from the table following the program that the two cases share the same loop and the exchange is different.
In fact, the exchange itself has a great relationship with the degree of order of the data source. when the data is in reverse order, the number of exchanges is the same as the number of cycles (each cycle will be exchanged ), the complexity is O (n * n ).
When the data is in positive order, there will be no exchange. The complexity is O (0 ). It is in the intermediate state in disordered order. For this reason, we usually compare algorithms by the number of cycles.

2. exchange method:

The procedures of the exchange method are the clearest and simplest. Each time, the current elements are compared and exchanged with the subsequent elements one by one.

Copy codeThe Code is as follows: # include <iostream. h>
Void ExchangeSort (int * pData, int Count)
{
Int iTemp;
For (int I = 0; I <Count-1; I ++)
{
For (int j = I + 1; j <Count; j ++)
{
If (pData [j] <pData)
{
ITemp = pData;
PData = pData [j];
PData [j] = iTemp;
}
}
}
}

Void main ()
{
Int data [] = {10, 9, 8, 7, 6, 5, 4 };
ExchangeSort (data, 7 );
For (int I = 0; I <7; I ++)
Cout <data <"";
Cout <"\ n ";
}

Reverse Order (worst case)
First round: 10, 9, 8, 7-> 9, 10, 8, 7-> 8, 10, 9-> 7, 10, 9, 8 (three exchanges)
Round 2: 7, 10, 9-> 7, 9, 10, 8-> 7, 8, 10, 9 (exchange twice)
First round: 7, 8, 10, 9-> 7, 8, 9, 10 (switching once)
Cycles: 6
Number of exchanges: 6

Others:
First round:,->, (exchange once)
Round 2: 7, 10, 8, 9-> 7, 8, 10, 9-> 7, 8, 10, 9 (exchange once)
First round: 7, 8, 10, 9-> 7, 8, 9, 10 (switching once)
Cycles: 6
Number of exchanges: 3

From the running table, the exchange is almost as bad as the bubble. This is true. The number of loops is also 1/2 * (n-1) * n, so the complexity of the algorithm is still O (n * n ). Because we cannot give all the information, we can only tell you that the exchange is equally bad (in some cases, slightly better, in some cases ). P # subtitle # e #

3. Selection Method:

Now we can finally see the hope: This method improves the performance (in some cases). This method is similar to our human sorting habits: select the smallest value exchange from the data and the second value exchange from the saved part.

Copy codeThe Code is as follows: # include <iostream. h>
Void SelectSort (int * pData, int Count)
{
Int iTemp;
Int iPos;
For (int I = 0; I <Count-1; I ++)
{
ITemp = pData;
IPos = I;
For (int j = I + 1; j <Count; j ++)
{
If (pData [j] <iTemp)
{
ITemp = pData [j];
IPos = j;
}
}
PData [iPos] = pData;
PData = iTemp;
}
}

Void main ()
{
Int data [] = {10, 9, 8, 7, 6, 5, 4 };
SelectSort (data, 7 );
For (int I = 0; I <7; I ++)
Cout <data <"";
Cout <"\ n ";
}

Reverse Order (worst case)
First round:,-> (iTemp = 9),-> (iTemp = 8),-> (iTemp = 7, 8, 10 (exchange once)
Round 2:,->, (iTemp = 8)-> (iTemp = 8), 8, 9, 10 (exchange once)
First round:,-> (iTemp = 9), (0 switching)
Cycles: 6
Number of exchanges: 2

Others:
Round 1:,-> (iTemp = 8),-> (iTemp = 7),-> (iTemp = 7), 10, 8, 9 (exchange once)
Round 2:,-> (iTemp = 8),-> (iTemp = 8), (exchange once)
First round:,-> (iTemp = 9), (exchange once)
Cycles: 6
Number of exchanges: 3
Unfortunately, the number of loops required by the algorithm is still 1/2 * (n-1) * n. Therefore, the algorithm complexity is O (n * n ).
Let's look at his exchange. Each outer loop generates only one exchange (only one minimum value ). So f (n) <= n
So we have f (n) = O (n ). Therefore, when data is messy, it can reduce the number of exchanges. 4. insert method:
The insertion method is more complex. The basic working principle is to draw a card, find the corresponding position in the front card, and then continue to the next

Copy codeThe Code is as follows: # include <iostream. h>
Void InsertSort (int * pData, int Count)
{
Int iTemp;
Int iPos;
For (int I = 1; I <Count; I ++)
{
ITemp = pData;
IPos = I-1;
While (iPos> = 0) & (iTemp <pData [iPos])
{
PData [iPos + 1] = pData [iPos];
IPos --;
}
PData [iPos + 1] = iTemp;
}
}

Void main ()
{
Int data [] = {10, 9, 8, 7, 6, 5, 4 };
InsertSort (data, 7 );
For (int I = 0; I <7; I ++)
Cout <data <"";
Cout <"\ n ";
}

Reverse Order (worst case)
First round: 10, 9, 8, 7-> 9, 10, 8, 7 (switching once) (loop once)
Round 2: 9, 10, 8, 7-> 8, 9, 10, 7 (switching once) (looping twice)
First round: 8, 9, 10, 7-> 7, 8, 9, 10 (switching once) (looping three times)
Cycles: 6
Number of exchanges: 3

Others:
First round: 8, 10, 7, 9-> 8, 10, 7, 9 (0 switching) (1 loop)
Round 2: 8, 10, 7, 9-> 7, 8, 10, 9 (switching once) (looping twice)
First round: 7, 8, 10, 9-> 7, 8, 9, 10 (switching once) (loop once)
Number of cycles: 4
Number of exchanges: 2

The behavior analysis at the end of the preceding section actually creates an illusion that this algorithm is the best in a simple algorithm, but it is not because its number of loops is not fixed, we can still use the O method. From the above results, we can see that the number of cycles f (n) <= 1/2 * n * (n-1) <= 1/2 * n. So its complexity is still O (n * n) (here, we will explain that the number of exchanges can still be deduced if it is not to show the differences in these simple sorting ). Now let's look at the switching. In terms of appearance, the number of switching times is O (n) (derivation is similar to the selection method), but we need to perform the '=' operation with the same number of inner loops each time. For a normal exchange, we need three times '=', but here we are obviously a little more, so we waste time. In the end, I personally think that the selection method is the best in simple sorting algorithms. Insert sort

Copy codeThe Code is as follows: # include <iostream>
Using namespace std;

Void coutstream (int a [], int n ){
For (int I = 0; I! = N; I ++)
Cout <a <"";
}

Void insertsort (int a [], int n ){
Int temp;
For (int I = 1; I <n; I ++)
{
Int j = I;
Temp = a; // store the data at location a first.
While (j> 0 & temp <a [J-1])
{
A [j] = a [J-1];
J --;
}
A [j] = temp;
}
}

Int main ()
{
Int a [5] = {, 4 };
Insertsort (a, 5); // insert sorting
Coutstream (a, 5 );//
Return 0;
}

Ii. advanced sorting algorithms:

In the advanced sorting algorithm, we will only introduce this one, and it is also the fastest I know (among the materials I have read. It still looks like a binary tree. First, we select a median value in the middle program. We use the median value in the array, and then place the values smaller than the median value on the left and the larger values on the right (the specific implementation is to find from both sides, find a pair of backend switches ). Then use this process on both sides (the easiest method -- recursion ).
1. Quick sorting:

Copy codeThe Code is as follows: # include <iostream. h>

Void run (int * pData, int left, int right)
{
Int I, j;
Int middle, iTemp;
I = left;
J = right;
Middle = pData [(left + right)/2]; // calculates the median value.
Do {
While (pData <middle) & (I <right) // The number of scans from the left greater than the value
I ++;
While (pData [j]> middle) & (j> left) // The number of scans from the right side greater than the value
J --;
If (I <= j) // a pair of values is found.
{
// Exchange
ITemp = pData;
PData = pData [j];
PData [j] = iTemp;
I ++;
J --;
}
} While (I <= j); // If the subscripts on both sides of the scan are staggered, stop (once completed)

// When the left part has a value (left <j), recursive left half edge
If (left <j)
Run (pData, left, j );
// When the right part has a value (right> I), recursive right Half Edge
If (right> I)
Run (pData, I, right );
}

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 <"";
Cout <"\ n ";
}

I have not provided behavior analysis here, because this is very simple. We will analyze the algorithm directly: first, we will consider the ideal situation.
1. The size of the array is the power of 2, so that the split can always be divisible by 2. Assume that it is the k power of 2, that is, k = log2 (n ).
2. Each time we select a value that is just a median value, the array can be classified.
First layer recursion, loop n times, second layer loop 2*(n/2 )......
So there are n + 2 (n/2) + 4 (n/4) +... + n * (n/n) = n +... + n = k * n = log2 (n) * n
Therefore, the algorithm complexity is O (log2 (n). In other cases, it is only worse than this. The worst case is that the middle selected each time is the minimum or maximum value, then it will become an exchange method (because recursion is used, the situation is worse ). But what do you think is the probability of such a situation ?? You don't have to worry about this issue. Practice has proved that quick sorting is always the best in most cases. If you are worried about this problem, you can use heap sorting, which is a stable O (log2 (n) * n) algorithm, but in general, the speed is slower than the quick sorting (because the heap needs to be reorganized)

Iii. Other sorting

1. Bidirectional bubbling:
Generally, the bubble is unidirectional, and here it is bidirectional, that is, reverse work is required.
The code looks complicated. After careful consideration, you can see that it is a round-trip method.
The author of this Code thinks this can reduce some exchanges on the basis of bubbling (I don't think so, maybe I am wrong ).
I think this is an interesting piece of code.

Copy codeThe Code is as follows: # include <iostream. h>
Void Bubble2Sort (int * pData, int Count)
{
Int iTemp;
Int left = 1;
Int right = Count-1;
Int t;
Do
{
// Positive part
For (int I = right; I> = left; I --)
{
If (pData <pData [I-1])
{
ITemp = pData;
PData = pData [I-1];
PData [I-1] = iTemp;
T = I;
}
}
Left = t + 1;

// Reverse part
For (I = left; I <right + 1; I ++)
{
If (pData <pData [I-1])
{
ITemp = pData;
PData = pData [I-1];
PData [I-1] = iTemp;
T = I;
}
}
Right = T-1;
} While (left <= right );
}

Void main ()
{
Int data [] = {10, 9, 8, 7, 6, 5, 4 };
Bubble2Sort (data, 7 );
For (int I = 0; I <7; I ++)
Cout <data <"";
Cout <"\ n ";
}

Quick sorting

Copy codeThe Code is as follows: # include <iostream>
Using namespace std;
Class QuickSort
{
Public:
Void quick_sort (int * x, int low, int high)
{
Int foreign tkey;
If (low {
Required tkey = partion (x, low, high );
Quick_sort (x, low, pivotkey-1 );
Quick_sort (x, repeated tkey + 1, high );
}
}
Int partion (int * x, int low, int high)
{
Int foreign tkey;
Required tkey = x [low];
While (low {
While (low -- High; // There Is A while LOOP that only executes this sentence
X [low] = x [high];
While (low + + Low; // and the while LOOP only executes this sentence
X [high] = x [low];
}
X [low] = repeated tkey;
Return low;
}
};
Int main ()
{
Int x [10] = };
QuickSort qs;
Qs. quick_sort (x, 0, 9 );
Cout <"the sorted numeric sequence is:" <endl;
For (int I = 0; I <10; I ++)
{
Printf ("% d", x );
}
Return 0;
}

2. SHELL sorting

This sorting is very complicated and you will know after reading the program.
First, we need a decreasing step. Here we use 9, 5, 3, and 1 (the last step must be 1 ).
The principle is to first sort all the content of 9-1 elements, and then sort 5-1 elements in the same way.

Copy codeThe Code is as follows: # include <iostream. h>
Void ShellSort (int * pData, int Count)
{
Int step [4];
Step [0] = 9;
Step [1] = 5;
Step [2] = 3;
Step [3] = 1;

Int iTemp;
Int k, s, w;
For (int I = 0; I <4; I ++)
{
K = step;
S =-k;
For (int j = k; j <Count; j ++)
{
ITemp = pData [j];
W = j-k; // calculate the subscript of the last step element
If (s = 0)
{
S =-k;
S ++;
PData [s] = iTemp;
}
While (iTemp <pData [w]) & (w> = 0) & (w <= Count ))
{
PData [w + k] = pData [w];
W = w-k;
}
PData [w + k] = iTemp;
}
}
}

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 <"";
Cout <"\ n ";
}

The program looks a little headache. But it is not very difficult. It is much easier to remove the s = 0 block. Here we should avoid using the 0 step to write code that causes program exceptions. This code is worth noting. This algorithm is named after the inventor D. L. SHELL. According to the reference: "Because of complex mathematical reasons, avoiding the power step of 2 can reduce the algorithm efficiency ." In addition, the complexity of the algorithm is the 1.2 power of n. We only have results because it is very complicated and "beyond the scope of this book" (I don't know the process. Bubble sorting performance optimized version # include <iostream>

Copy codeThe Code is as follows: using namespace std;
Void maopao (int * list, int n)
{
Int I = n, j, temp;
Bool exchange; // exit the loop when the data has been sorted
For (I = 0; I <n; I ++)
{
Exchange = false;
For (j = 0; j <n-i-1; j ++)
{
If (list [j]> list [j + 1])
{
Temp = list [j];
List [j] = list [j + 1];
List [j + 1] = temp;
Exchange = true;
}

}
If (! Exchange)
{
Return;
}
}
}
Int main ()
{
Int a [7] = {32, 43, 30 };
Maopao (a, 7 );
For (int I = 0; I <7; I ++)
Cout <a <"";
Return 0;
}

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.