常见排序算法-冒泡排序
Posted 咸鱼成长小站
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了常见排序算法-冒泡排序相关的知识,希望对你有一定的参考价值。
排序是我们再日常开放中常常需要做的事,虽然我们可以直接使用标准库里的sort函数,但是了解一些排序算法的原理是非常有必要的。
冒泡排序是一种比较简单的排序算法,在常见的排序算法时间复杂度较高,效率比较低。因此也不是很常用,但是我们还是需要掌握的。
冒泡排序之所以叫“冒泡”。缘于它的排序过程,小的数会像冒泡泡一样的向前浮,
它的实现也非常简单,每一趟排序,只需要从第一个数开始,比较它和它后面的数。如果前一个数大于后一个数,则交换它们,这样就使得大的数向后挪了一位,重复这样的过程比较第二个数和第三个数,一直比较到最后两个未排序的数。这就完成了一趟排序,这样的一趟排序就能将当前最大的数挪到数组的最后。
而第二趟排序,依旧从第一位开始,比较它和它后面的那个数,将大的数往后挪,一直比较到最后一位数前的两个数。因为最后一个数已经是有序的了,所以只需要最后一位数的前面两位比较就可以将第二大的数挪到倒数第二位。
剩下的操作都一致,唯一变化的就是比较的次数,每有一个数有序,比较的次数就少一次。
下面用一个例子来演示一下:
我们有一个未排序数组:[8,7,6,9,5,4,2,1,3]
第一趟排序
首先比较第一位和第二位,8 > 7所以我们交换这两个数,变为
[7,8,6,9,5,4,2,1,3]
然后比较第二位和第三位,8 > 6所以我们继续交换这两个数,变为
[7,6,8,9,5,4,2,1,3]
第三次比较,9 > 8所以不用交换,继续向下走
[7,6,8,9,5,4,2,1,3]
……
第七次比较,比较倒数第三位和倒数第二位。交换1和9
[7,6,8,5,4,2,1,9,3]
最后一次比较,也就是比较最后两位,9 > 3,所以交换9和3
[7,6,8,5,4,2,1,3,9]
这样就完成了一趟排序,成功的将最大的数9挪到了最后一位,而比9小的数字都被冒到了前面。
第二趟排序
[6,7,5,4,2,1,3,8,9]
第三趟排序
[6,5,4,2,1,3,7,8,9]
第四趟排序
[5,4,2,1,3,6,7,8,9]
第五趟排序
[4,2,1,3,5,6,7,8,9]
第六趟排序
[2,1,3,4,5,6,7,8,9]
第七趟排序
[1,2,3,4,5,6,7,8,9]
这时,我们就得到了一个有序的数组。在这个例子我们只执行了七趟排序,但第七趟确认的是第三位数。只是这一趟排序过后第一位第二位刚好有序,所以我们还差一次比较第一位和第二位的运算。
第八趟排序
[1,2,3,4,5,6,7,8,9]
我们之前说过,冒泡排序的时间复杂度是不低的。我们来计算一下它的时间复杂度,对于N个数来说,冒泡排序需要N-1趟排序才能使其有序,而每一趟排序,都包含了N-1次比较和交换的过程。所以它的时间复杂度为O(n^2)。并且与原数组是否有序无关。
不过,我们可以通过优化算法,将冒泡排序的最优时间复杂度缩减为O(n),方法就是使用一个布尔变量,判断在一趟排序中,是否有交换的操作,如果没有交换两个数的操作,就表明这个数组已经是有序的了,然后直接break跳出即可。
具体的代码如下:
1#include <iostream>
2
3template <typename T>
4void bubble_sort(T *arr,int len){
5 bool isOrdered = true;
6 for(int i = 0;i < len-1;i++){
7 isOrdered = true;
8 for(int j = 0;j < len-i-1;j++){
9 if(arr[j] > arr[j+1]){
10 isOrdered = false;
11 arr[j] += arr[j+1];
12 arr[j+1] =arr[j] - arr[j+1];
13 arr[j] -= arr[j+1];
14 }
15 }
16 if(isOrdered)
17 break;
18 }
19}
20int main(){
21 int arr[9] = {8,7,6,9,5,4,2,1,3};
22 int len = sizeof(arr)/sizeof(arr[0]);
23 bubble_sort(arr,len);
24 for(int i = 0;i < len;i++){
25 std::cout<<arr[i]<<" ";
26 }
27 std::cout<<std::endl;
28 return 0;
29}
以上是关于常见排序算法-冒泡排序的主要内容,如果未能解决你的问题,请参考以下文章