• 冒泡排序(交换排序)-八大排序汇总(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 }
  • 相关阅读:
    在 ASP.NET 2.0 中上载文件
    ASP.NET(C#)FileUpload实现上传限定类型和大小的文件到服务器<from Copying>
    aspnetupload 上传组件在VS2008中使用详细说明
    基于asp.net 的文件上传和下载~~~转
    设置竖直的分割符【使用div】 (根据屏幕的大小自适应)
    分隔线
    UGUI事件系统
    U3D音频系统
    Unity启动事件-监听:InitializeOnLoad
    VS生成桌面应用程序
  • 原文地址:https://www.cnblogs.com/SnailProgramer/p/4854189.html
Copyright © 2020-2023  润新知