冒泡排序(交换排序)-八大排序汇总(3)

基本思想

  两两相邻元素之间的比较,如果前者大于后者,则交换

  设数组长度为N。

  1.比较相邻的前后二个数据,如果前面数据大于后面的数据,就将二个数据交换。

  2.这样对数组的第0个数据到N-1个数据进行一次遍历后,最大的一个数据就“沉”到数组第N-1个位置。

  3.N=N-1,如果N不为0就重复前面二步,否则排序完成。

稳定性

  冒泡排序是一种稳定的排序算法

时间复杂度

  若文件的初始状态是正序的,一趟扫描即可完成排序。所需的关键字比较次数 和记录移动次数  均达到最小值:  ,  。所以,冒泡排序最好的时间复杂度为 

  若初始文件是反序的,需要进行  趟排序。每趟排序要进行 次关键字的比较(1≤i≤n-1),且每次比较都必须移动记录三次来达到交换记录位置(swap函数)。在这种情况下,比较和移动次数均达到最大值:

  
  
空间复杂度
  O(1)
使用场景
  冒泡排序是一种效率低下的排序方法,在数据规模很小时,可以采用。数据规模比较大时,最好用其它排序方法。
分析及代码

原始待排序数组| 6 | 2 | 4 | 1 | 5 | 9 |

第一趟排序(外循环)

第一次两两比较6 > 2交换(内循环)

交换前状态| 6 | 2 | 4 | 1 | 5 | 9 |   交换后状态| 2 | 6 | 4 | 1 | 5 | 9 |

第二次两两比较,6 > 4交换

交换前状态| 2 | 6 | 4 | 1 | 5 | 9 |   交换后状态| 2 | 4 | 6 | 1 | 5 | 9 |

第三次两两比较,6 > 1交换

交换前状态| 2 | 4 | 6 | 1 | 5 | 9 |   交换后状态| 2 | 4 | 1 | 6 | 5 | 9 |

第四次两两比较,6 > 5交换

交换前状态| 2 | 4 | 1 | 6 | 5 | 9 |   交换后状态| 2 | 4 | 1 | 5 | 6 | 9 |

第五次两两比较,6 < 9不交换

交换前状态| 2 | 4 | 1 | 5 | 6 | 9 |   交换后状态| 2 | 4 | 1 | 5 | 6 | 9 |

第二趟排序(外循环)

第一次两两比较2 < 4不交换

交换前状态| 2 | 4 | 1 | 5 | 6 | 9 |   交换后状态| 2 | 4 | 1 | 5 | 6 | 9 |

第二次两两比较,4 > 1交换   

交换前状态| 2 | 4 | 1 | 5 | 6 | 9 |    交换后状态| 2 | 1 | 4 | 5 | 6 | 9 |

第三次两两比较,4 < 5不交换

交换前状态| 2 | 1 | 4 | 5 | 6 | 9 |    交换后状态| 2 | 1 | 4 | 5 | 6 | 9 |

第四次两两比较,5 < 6不交换

交换前状态| 2 | 1 | 4 | 5 | 6 | 9 |   交换后状态| 2 | 1 | 4 | 5 | 6 | 9 |

第三趟排序(外循环)

第一次两两比较2 > 1交换

交换后状态| 2 | 1 | 4 | 5 | 6 | 9 |   交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |

第二次两两比较,2 < 4不交换

交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |    交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |

第三次两两比较,4 < 5不交换

交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |    交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |

第四趟排序(外循环)无交换

第五趟排序(外循环)无交换

 1 #include "stdafx.h"
 2 #include <iostream>
 3 using namespace std;
 4 
 5 void print(int a[], int n ,int i)
 6 {  
 7     cout<<""<<i+1 <<"趟 : ";  
 8     for(int j= 0; j<n; j++)
 9     {  
10         cout<<a[j] <<"  ";  
11     }  
12     cout<<endl;  
13 }    
14 
15 void bubbleSort(int a[], int n)
16 {  
17     for(int i =0 ; i< n-1; ++i) 
18     {  
19         for(int j = 0; j < n-1-i; ++j) //for(int j = n-1; j > i; j--)
20         {  
21             if(a[j] > a[j+1])  
22             {  
23                 int tmp = a[j] ; 
24                 a[j] = a[j+1] ;  
25                 a[j+1] = tmp;  
26             }  
27         }      
28         print(a,n,i);
29     }  
30 } 
31 
32 int main(int argc, char* argv[])
33 {
34     int a[6] = {6,2,4,1,5,9};  
35  
36     bubbleSort(a, 6); 
37     return 0;
38 }

可以看到,从第三次交换后就已经排好序了,之后的比较是多余的,所以可以加一个标志,如果一次循环中没有交换过元素,则说明已经排好序。

 1 void print(int a[], int n ,int i)
 2 {  
 3     cout<<""<<i+1 <<"趟 : ";  
 4     for(int j= 0; j<n; j++)
 5     {  
 6         cout<<a[j] <<"  ";  
 7     }  
 8     cout<<endl;  
 9 }    
10 
11 void bubbleSort(int a[], int n)
12 {  
13     bool isChanged = false;
14     for(int i =0 ; i< n-1; ++i) 
15     {  
16         isChanged = false;
17         for(int j = 0; j < n-1-i; ++j) //for(int j = n-1; j > i; j--)
18         {  
19             if(a[j] > a[j+1])  
20             {  
21                 int tmp = a[j] ; 
22                 a[j] = a[j+1] ;  
23                 a[j+1] = tmp;  
24 
25                 isChanged = true;
26             }  
27         }      
28         print(a,n,i);
29         if(isChanged == false)
30             break;        
31     }  
32 } 
33 
34 int main(int argc, char* argv[])
35 {
36     int a[6] = {6,2,4,1,5,9};  
37  
38     bubbleSort(a, 6); 
39     return 0;
40 }

  再做进一步的优化。如果有100个数的数组,仅前面10个无序,后面90个都已排好序且都大于前面10个数字,那么在第一趟遍历后,最后发生交换的位置必定小于10,且这个位置之后的数据必定已经有序了,记录下这位置,第二次只要从数组头部遍历到这个位置就可以了。

 1 //冒泡排序3
 2 void BubbleSort3(int a[], int n)
 3 {
 4     int j, k;
 5     int flag;
 6     
 7     flag = n;
 8     while (flag > 0)
 9     {
10         k = flag;
11         flag = 0;
12         for (j = 1; j < k; j++)
13             if (a[j - 1] > a[j])
14             {
15                 Swap(a[j - 1], a[j]);
16                 flag = j;
17             }
18     }
19 }
原文地址:https://www.cnblogs.com/SnailProgramer/p/4854189.html