十大内排序之冒泡排序(C++、Java实现)
冒泡排序(从低到高)
排序思路
冒泡排序又称为气泡排序,是一种典型的交换排序方法。初学者在学习编程语言或者学习算法时,都会碰到这个排序方法。其基本思路为:通过相邻元素关键字比较,从而交换元素的位置,使得关键字较小的元素如气泡一般,向上“浮动”;直至浮出水面。
首先,我们将待排序的元素分为两个区域,一个为有序区,另一个为无序区。排序之初,所有元素都在无序区,有序区拥有0个元素。然后开始进行元素的关键字比较,这里要注意,我们是从无序区的最末端开始进行两两比较,比较之后将关键字小的元素放在前面,关键字大的元素放在后面,直至整个无序区的所有元素都进行了比较。这时无序区里最小的元素已经如气泡一般冒到了水面。这时我们将最小的元素纳入有序区,然后再比较无序区里面的元素,直至所有元素进入有序区。
排序准备
C++代码的实现:我们选取顺序表作为排序所使用的数据结构,编写了两个函数,一个作为主要排序函数,另一个为在控制台打印顺序表中的元素。二者参数列表均为顺序表的头指针和顺序表的长度。
- 主要排序函数原型void BubbleSort(RecType * re,int n);
- 顺序表输出函数声明void OutputRecType(RecType * r,int n);
- 原始数据:2,54 ,33,22,24,96,56,67,32,26 ;
Java代码的实现:我们选取最简单的数组来进行排序,同样编写两个函数来完成排序与数组打印的功能;与上述基本相同
C++代码实现
#include<iostream>
//使用顺序表作为排序所用的数据结构
typedef struct
{
//定义关键字
int key;
}RecType;
//声明常量顺序表的最大长度
const int MaxSize = 10;
//函数原型声明
void BubbleSort(RecType * re,int n);
void OutputRecType(RecType * r,int n);
//主函数
int main()
{
//命名空间
using namespace std;
//原始数据表
RecType rec[MaxSize]={{2},{54},{33},{22},{24},{96},{56},{67},{32},{26}};
//输出原始数据
cout<< "原始数据:";
OutputRecType(rec,MaxSize);
//冒泡排序
BubbleSort(rec,MaxSize);
//输出排序后的数据
cout<< "冒泡排序后数据:";
OutputRecType(rec,MaxSize);
}
//冒泡排序函数
void BubbleSort(RecType * r,int n)
{
using namespace std;//命名空间
//创建一个用于交换的中间变量
int swap;
//双重循环 ===变量i表示交换的轮数 ====变量j表示每1轮交换的次数
for(int i = 0 ; i < n - 1; i++ )
{
for(int j = n-1 ; j > i ; j--)
{
if(r[j].key < r[j-1].key)
{
swap = r[j].key;
r[j].key = r[j-1].key;
r[j-1].key = swap;
}
}
}
}
//输出顺序表的函数
void OutputRecType(RecType * r,int n)
{
//命名空间
using namespace std;
for(int i = 0 ; i < n ; i++)
{
cout<<r[i].key<<" ";
}
cout<<endl;
}
java代码实现
public class BubbleSort {
/**
* 冒泡排序:按照从小到大顺序
* @param args
*/
public static void main(String[] args) {
int Rec[]={2,54,33,22,24,96,56,67,32,26};
System.out.print("原始数据 : ");
PrintArray(Rec , 10);
BubbleSort(Rec , 10);
System.out.print("排序之后数据 : ");
PrintArray(Rec , 10);
}
/**
* 冒泡排序
* @param rec
* @param n
*/
public static void BubbleSort(int rec[], int n) {
int swap;
for(int i = 0;i < n-1;i++){
for(int j = n-1 ; j >i ; j--){
if(rec[j] < rec[j-1]){
swap = rec[j];
rec[j] = rec[j-1];
rec[j-1] = swap;
}
}
}
}
/**
* 打印数组的每一个元素
* @param arry
* @param n
*/
public static void PrintArray(int arry[],int n) {
for(int i = 0 ; i < n ; i ++){
System.out.print(arry[i]+" ");
}
System.out.println("");
}
}
算法分析(主要分析时间复杂度与稳定性)
时间复杂度
- 如果初始数据序列是正序的,换而言之是已经排好的序列,假设该序列拥有n个元素,那么我们所需的关键字比较的次数与元素移动的次数达到最小。关键字比较n-1次,元素移动0次。
- 如果初始序列是最糟糕的情况,换而言之该序列为反序,在这种情况下,比较次数与移动次数均达到最大,我们不难计算出关键字比较次数为 n(n-1)/2,移动次数为3n(n-1)/2。
- 平均情况分析复杂一些,因为算法可能在中间的某一道排序完成后就终止了。但是可以证明平均的排序趟数仍为O(n),由此可以得出平均情况下总的比较次数仍为平方级 O(n^ 2),所以算法的平均时间复杂度为平方级O(n^2)。
稳定性
- 在冒泡排序中只是用了i、j、swap这三个辅助变量,与问题规模n无关,所以辅助空间复杂度为O(1),也就是说他是一个就地排序。换而言之,当两个关键字一样的元素同时出现在同一个顺序表里,当排序过后它们的相对位置并不会因为排序而发生改变。所以冒泡排序是一种稳定的排序算法。