C++算法之冒泡排序
一、基本思想
试想一下,如果在上体育课的时候,通常学生都会随意站成一列,但是体育老师会帮忙调整学生的站位使得最终顺序是按照身高排序的。那么,回忆一下体育老师是如何调整顺序的呢?
假设体育老师想将学生从左到右按照身高从矮到高排序。通常情况下,他会从左到右扫视学生的身高。如果左边有一个同学,个子比右边的同学高,他就要将其进行调整。具体调整方法是:
如果一个同学比他右边的同学高,就让这两个同学交换位置。
如果交换过后,这个同学仍然比新的右边的同学高,那么继续交换,直到他不在比右边的同学高。这样进行了若干次以后,队列就按照身高排好序了。
那么,如何严谨地表述“体育老师排序方法”,并对于任意给定的序列,都能将其从小到大排好序呢?
回忆在介绍选择排序的时候,我们的具体思路如下:
我们发现,这里我们使用了将原问题转换为规模更小的子问题的思路。
所以在选择排序的过程,相当于每次将当前序列未排序部分的最小元素归位,将未排序的序列长度缩小一位。同样,如果我们能够通过某种方式,把序列中的最大值移动到序列最后面,也可以起到将未排序序列长度缩小一位的效果。
通过“体育老师交换方法”,使得每次我们都能把最大值移动到序列的最后一位。
利用上面的步骤进行问题转换,将未排序的序列长度缩减一个。
这就是冒泡排序的具体思路,而上面提到的“将最大值移动到最后一位”的操作,就叫做冒泡操作。
二、步骤
冒泡排序
1、冒泡排序分为n-1
个阶段。
在第1
个阶段,通过“冒泡”,将前n
个元素的最大值移动到序列的最后一位。此时只剩前n-1
个元素未排序。
2、在第i
个阶段,此时序列前n-i+1
个元素未排序。通过“冒泡”,我们将前n-i+1
个元素中的最大值移动到最后一位。此时只剩前n-i
个元素未排好序。
3、最终到第n-1
个阶段,前2
个元素未排序。将其中的较大值移动到后一位,则整个序列排序完毕。
4、在上面的算法过程中,我们提到“冒泡”将序列中的最大值移动到最后一位。下面,我们介绍一下“冒泡”的过程:
冒泡过程
对于长度为n
的序列,如何将其中的最大值移动到最后一位?
就像上面说的那样,如果相邻两个元素(如下图2和3),第一个大,第二个小,那么,将两个元素交换。
如果我们对一段序列从左到右连续做如下交换操作:
if (a[i] > a[i + 1]) swap(a[i], a[i + 1]);
它的效果相当于将每一个”极大值“元素,移动到能到达的最远的位置。
自然,序列中的最大值,也是一个极大值,而它能被移动到的最远的位置,就是序列的最后一位。
所以,如果对于序列的1~n
位,想将其中的最大元素”冒泡“到最后一位,那么就需要从第1
位开始,一直到第n-1
位,依次进行上面的交换过程。
三、代码
代码如下(示例):文章来源:https://www.toymoban.com/news/detail-630535.html
#include <bits/stdc++.h>
#define N 1010
using namespace std;
int n = 6; // 待排序的元素个数为6
int a[N] = {0, 2, 3, 2, 11, 7, 6}; // 待排序元素 {2,3,2,11,7,6}
int main() {
// 连续交换过程
// 一共n-1个阶段,在第i个阶段,未排序序列长度从n-i+1到n-i。
for (int i = 1; i < n; ++i) {
// 将序列从1到n-i+1的最大值,移到n-i+1的位置
for (int j = 1; j <= n - i; ++j)
// 其中j枚举的是前后交换元素的前一个元素序号
// TODO 请补全代码完成阶段的冒泡过程
if (a[j] > a[j + 1])
swap(a[j], a[j + 1]);
}
// 输出
for (int i = 1; i <= n; ++i) cout << a[i] << ' ';
cout << endl;
return 0;
}
四、复杂度分析
从代码中,我们可以看到冒泡排序的主干部分有两层循环,并且每一层的循环次数都在O(n)
左右的数量级。所以完整的冒泡排序时间复杂度是O(n^2)
文章来源地址https://www.toymoban.com/news/detail-630535.html
到了这里,关于C++算法之冒泡排序的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!