以数组A={5,3,2,4,1}为例,我们对其使用冒泡排序法时,排序过程如图3.4所示。
在上述冒泡排序的算法中,数据从数据开头逐一完成排序。也就是说,步骤1到步骤4的处理结束后,数据中最小的元素将移至数组开头的A[0]位置。同理,步骤5到步骤7结束后,数据中第二小的元素会移动至A[1],然后步骤8到步骤9确定A[2],步骤10确定A[3],依次类推,逐一确定已排序部分末尾要追加的元素。
从例子中很容易能看出,程序每完成依次外层循环,已排序部分就增加一个元素。这样一来,程序外层循环最多需执行N次,同时内层循环的处理范围也会逐渐减小。因此,我们可以发挥外层循环变量i的作用,对冒泡排序的算法做如Program3.1所示的修改。
Program3.1 冒泡排序法的实现
bubbleSort()
flag=1
i=0 //未排序部分的起始下标
while flag
flag=0
for j从N-1到i+1
if A[j] < A[j-1]
A[j]与A[j-1]交换
flag=1
i++
实现该冒泡排序法时需要的主要变量如图3.5所示。
考察
冒泡排序法仅对数组中的相邻元素进行比较和交换,因此键相同的元素不会改变顺序。所以冒泡排序法也属于一种稳定排序的算法。但要注意的是,一旦将比较运算A[j]<A[j-1]改为A[j]<=A[j-1],算法就会失去稳定性。
然后我们考虑一下冒泡排序法的复杂度。假设数据总量为N,冒泡排序法需对未排序部分的相邻元素进行(N-1)+(N-2)+...+1=(N^2-N)/2次比较。也就是说,冒泡排序法在最坏情况下需要进行(N^2-N)/2次比较运算,算法复杂度数量级为O(N^2)。
顺便一提,冒泡排序法中的交换次数又称为反序数或逆序数,可用于体现数列的错乱承德。
C++版本:
#include<iostream>
using namespace std;
//使用flag的冒泡排序法
int bubbleSort(int A[],int N){
int sw=0;
bool flag=1;
for(int i=0;flag;i++){
flag=0;
for(int j=N-1;j>=i+1;j--){
if(A[j]<A[j-1]){
//交换相邻元素
swap(A[j],A[j-1]);
flag=1;
sw++;
}
}
}
return sw;
}
int main(){
int A[100],N,sw;
cin>>N;
for(int i=0;i<N;i++)
cin>>A[i];
sw=bubbleSort(A,N);
for(int i=0;i<N;i++){
if(i)
cout<<" ";
cout<<A[i];
}
cout<<endl;
cout<<sw<<endl;
return 0;
}
Python版本:
n = int(input())
a = list(map(int,input().strip().split()))
count = 0
for i in range(n):
for j in range(n-1,i,-1):
if a[j] < a[j-1]:
a[j],a[j-1] = a[j-1],a[j]
count += 1
print(' '.join(map(str,a)))
print(count)
PHP版本:
<?php
fscanf(STDIN, "%d", $n);
$format = join(' ', array_fill(0, $n, '%d'));
$nums = array_map('intval', fscanf(STDIN, $format));
$count = bubble_sort($nums);
echo join(' ', $nums)."\n";
echo "$count\n";
function bubble_sort(&$nums)
{
$count = 0;
$need_to_sort = true;
while ($need_to_sort) {
$need_to_sort = false;
for ($i = count($nums)-1; $i > 0; $i--) {
if ($nums[$i-1] <= $nums[$i]) {
continue;
}
$tmp = $nums[$i];
$nums[$i] = $nums[$i-1];
$nums[$i-1] = $tmp;
$need_to_sort = true;
$count++;
}
}
return $count;
}
JAVA版本:
import java.io.*;
class Main{
public static int maxv(int x, int y){
if(x >= y){
return x;
}else{
return y;
}
}
public static int minv(int x, int y){
if(x <= y){
return x;
}else{
return y;
}
}
public static void main(String[] args){
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
try {
int N = Integer.parseInt(reader.readLine());;
String line = reader.readLine();
String[] strAry = line.split(" ");
int[] a = new int[N];
for (int i = 0;i < N; i++){
a[i] = Integer.parseInt(strAry[i]);
}
int count = 0;
while(true){
int v = 0;
for(int i = 0; i < (N -1); i++){
if(a[i + 1] < a[i]){
int k = a[i];
a[i] = a[i+1];
a[i + 1] = k;
count += 1;
v = 1;
}
}
if(v == 0){
break;
}
}
for(int i = 0; i < N; i++){
System.out.print(a[i]);
if(i != (N - 1)){
System.out.print(" ");
}
}
System.out.println();
System.out.println(count);
} catch (IOException e) {
//TODO: handle exception
System.out.println(e);
}
}
}
JavaScript版本:var input = require('fs').readFileSync('/dev/stdin', 'utf8');
var lines = input.split('\n');
var n = lines[0];
var A = lines[1].split(' ').map(function(i) {
return i - 0;
});
var cnt = 0;
for (var i = 0; i < n; i++) {
for (var j = n - 1; j > i; j--) {
if (A[j] < A[j - 1]) {
var tmp = A[j];
A[j] = A[j - 1];
A[j - 1] = tmp;
cnt++;
}
}
}
console.log(A.join(' '));
console.log(cnt);
C#版本:using System;
class Program{
public static void Main(){
var N=int.Parse(Console.ReadLine());
var s=Console.ReadLine().Split(' ');
var A=new int[N];
for(var i=0; i<N; i++){
A[i]=int.Parse(s[i]);
}
var cnt=0;
for(var i=0; i<N; i++){
for(var j=N-1; j>i; j--){
if(A[j]<A[j-1]){
cnt++;
var tmp=A[j];
A[j]=A[j-1];
A[j-1]=tmp;
}
}
}
for(var i=0; i<N; i++){
if(i>=N-1){
Console.WriteLine(A[i]);
} else{
Console.Write(A[i]+" ");
}
}
Console.WriteLine(cnt);
}
}