C++ 冒泡排序算法的实现与改进(含笔试面试题)

来源:互联网 发布:linux mount 共享目录 编辑:程序博客网 时间:2024/06/05 02:39
      冒泡排序(Bubble sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端


算法步骤:

1)比较相邻的元素。如果第一个比第二个大,就交换他们两个。

2)对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。

3)针对所有的元素重复以上的步骤,除了最后一个。

4)持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。


实现代码:包含标准冒泡程序和两次的改进,并使用了函数的重载、标准库容器等等

/*************************************************************************** *  @file       main.cpp *  @author     MISAYAONE *  @date       24  March 2017 *  @remark     24  March 2017  *  @theme      Bubble Sort  ***************************************************************************/#include <iostream>#include <vector>using namespace std;//传入数组首尾指针,标准冒泡排序void Bubble_sort(int *begin, int *end){for (auto p1 = begin; p1 != end; ++p1){for (auto p2 = begin; p2 != end-1; ++p2){if (*p2 > *(p2+1)){int val_temp = *p2;*p2 = *(p2+1);*(p2+1) = val_temp;}}}}//对函数进行重载,传入一对迭代器,同时进行第一次改进//第一次改进:用于标志某一趟排序过程中是否有数据交换//如果进行某一趟排序时并没有进行数据交换,则说明数据已经按要求排列好//可立即结束排序,避免不必要的比较过程void Bubble_sort(vector<int>::iterator begin, vector<int>::iterator end){int flag= 0;for (auto p1 = begin; p1 != end; ++p1){flag = 0;for (auto p2 = begin; p2 != end-1; ++p2){if (*p2 > *(p2+1)){int val_temp = *p2;*p2 = *(p2+1);*(p2+1) = val_temp;flag = 1;//表示此轮循环进行了交换}}if (flag == 0)//上一轮循环中未进行交换,直接跳出{break;}}}//对函数进行重载,传入数组指针和数组大小,同时进行第二次改进/*第二次改进:传统冒泡排序中每一趟排序操作只能找到一个最大值或最小值*//*我们考虑利用在每趟排序中进行正向和反向两遍冒泡的方法一次可以得到两个最终值(最大者和最小者)*//*从而使排序趟数几乎减少了一半*/void Bubble_sort(int a[],int size){int low = 0;int high = size-1;while(high > low){for (int i = low; i != high; ++i)//正向冒泡,确定最大值{if (a[i] > a[i+1]){int temp = a[i];a[i] = a[i+1];a[i+1] = temp;}}--high;for (int j = high; j != low; --j)//反向冒泡,确定最小值{if (a[j] < a[j-1]){int temp = a[j];a[j] = a[j-1];a[j-1] = temp;}}++low;}}int main(int argc,char** argv){int a[10] = {1,5,8,7,9,6,4,3,2,0};int b[10] = {1,5,8,7,9,6,4,3,2,0};vector<int> vec(a,a+10);Bubble_sort(begin(a),end(a));//标准库的begin()和end()函数cout<<"内置数组冒泡排序后:";for (int i = 0; i < 10; ++i){cout<<a[i]<<" ";}Bubble_sort(vec.begin(),vec.end());//标准库容器的begin()和end()成员函数cout<<endl;cout<<"第一次改进的冒泡排序后:";for (int i = 0; i < 10; ++i){cout<<vec[i]<<" ";}Bubble_sort(b,10);//传入参数为数组指针和数组大小cout<<endl;cout<<"第二次改进的冒泡排序后:";for (int i = 0; i < 10; ++i){cout<<b[i]<<" ";}cin.get();return 0;}


一般我们学到的第一个排序算法就是冒泡排序,这在面试笔试中是一个很常见的考点,平均时间空间复杂度,最好最坏情况下的时间空间复杂度,在不同情况下每一趟的比较次数,以及加标志位减少比较次数等,都是需要注意的地方。


复杂度分析:

冒泡排序对 n 个元素需要 O(n^2) 的比较次数,且可以原地排序,无需辅助空间。

冒泡排序仅适用于对于含有较少元素的数列进行排序。

最差时间复杂度 O(n^2)
平均时间复杂度 O(n^2)
最优时间复杂度 O(n)
最差空间复杂度 O(n),辅助空间 O(1)


特点分析:稳定算法(stable)、in place算法


例题1:对于整数序列100,99,98,…3,2,1,如果将它完全倒过来,分别用冒泡排序,它们的比较次数和交换次数各是多少?


答:冒泡排序的比较和交换次数将最大,都是1+2+…+n-1=n(n-1)/2=50×99=4545次。


例题2:把一个字符串的大写字母放到字符串的后面,各个字符的相对位置不变,不能申请额外的空间

#include <iostream>#include <vector>#include <string>using namespace std;//传入首尾迭代器void Bubble_sort1(string::iterator begin, string::iterator end){for (auto p1 = begin; p1 != end; ++p1){for (auto p2 = begin; p2 != end-1; ++p2){if (*p2 >= 'A' && *p2 <= 'Z')//是大写字母就往后传递{int val_temp = *p2;*p2 = *(p2+1);*(p2+1) = val_temp;}}}}int main(int argc,char** argv){string test = "sadhiUASVoijiashKUASYUI";Bubble_sort1(test.begin(),test.end());cout<<test<<endl;cin.get();return 0;}

1 0