冒泡排序法
冒泡排序法其实就是交换排序的一种,即两两比较待排序记录的关键字,发现两个记录的次序相反时即进行交换,直到没有反序的记录为止。
冒泡排序的基本概念是:依次比较相邻的两个数,将小数放在前面,大数放在后面。即首先比较第1个和第2个数,将小数放前,大数放后。然后比较第2个数和第3个数,将小数放前,大数放后,如此继续,直至比较最后两个数,将小数放前,大数放后。重复以上过程,直至最终完成排序。由于在排序过程中总是小数往前放,大数往后放,相当于气泡往上升,所以称作冒泡排序。(如附件图1)
冒泡排序的基本思想:
将被排序的记录数组 R[1..n] 假定为垂直排列,每个记录 R[i] 看做是重量为 R[i].key 的气泡。根据轻气泡不能在重气泡之下的原则,从下往上扫描数组 R 。凡扫描到违反本原则的轻气泡,就使其向上“漂浮”。如此反复进行,直到最后任何两个气泡都是轻者在上,重者在下为止。
(1) 初始, R[1..n] 为无序区。
(2) 第一趟扫描,从无序区底部向上依次比较相邻的两个气泡的重量,若发现轻者在下、重者在上,则交换二者的位置。即依次比较 (R[n],R[n-1]) 、 (R[n-1],R[n-2]) 、 … 、 (R[2],R[1]); 对于每对气泡 (R[j+1],R[j]), 若 R[j+1].key<R[j].key, 则交换 R[j+1] 和 R[j] 的内容。
第一趟扫描完毕时,“最轻”的气泡就飘浮到该区间的顶部,即关键字最小的记录被放在最高位置 R[1] 上。
(3) 第二趟扫描,扫描 R[2..n]。扫描完毕时,“次轻”的气泡飘浮到 R[2] 的位置上 …… 最后,经过 n-1 趟扫描可得到有序区 R[1..n]。
注意:第 i 趟扫描时, R[1..i-1] 和 R[i..n] 分别为当前的有序区和无序区。扫描仍是从无序区底部向上直至该区顶部。扫描完毕时,该区中最轻气泡漂浮到顶部位置 R[i] 上,结果是 R[1..i] 变为新的有序区。 (如附件图2)
因为每一趟排序都使有序区增加了一个气泡,在经过 n-1 趟排序之后,有序区中就有 n-1 个气泡,而无序区中气泡的重量总是大于等于有序区中气泡的重量,所以整个冒泡排序过程至多需要进行 n-1 趟排序。
若在某一趟排序中未发现气泡位置的交换,则说明待排序的无序区中所有气泡均满足轻者在上,重者在下的原则,因此,冒泡排序过程可在此趟排序后终止。为此,在下面给出的算法中,引入一个交换标志exchange, 在每趟排序开始前,先将其置为0。若排序过程中发生了交换,则将其置为1。各趟排序结束时检查 exchange, 若未曾发生过交换则终止算法,不再进行下趟排序。
package com.itttop.sort;
public class BubbleSort {
public static void main(String[] args) {
int[] R = new int[11];// R(1..10) 是待排序的文件,采用自下向上扫描,对R 做冒泡排序
int i, j;
System.out.println("排序前的数列为:\n");
for (i = 1; i < R.length; i++) {
R[i] = (int) (Math.random() * 100);
System.out.print(R[i] + "\t");
}
int exchange; // 交换标志
for (i = 1; i < R.length; i++) // 最多做11-1=10 趟排序
{
exchange = 0;// 本趟排序开始前,交换标志为0
for (j = 9; j >= i; j--)
{
// 对当前无序区R[i..10] 自下向上扫描
if (R[j + 1] < R[j])// 交换记录
{
R[0] = R[j + 1]; // R[0] 用于交换,仅做暂存单元
R[j + 1] = R[j];
R[j] = R[0];
exchange = 1; // 发生了交换,故将交换标志置1
}
}
if (exchange == 0)// 本趟排序未发生交换,提前终止算法
{
break;
}
}
System.out.println("\n" + "排序后的数列为:\n");
for (int k = 1; k < R.length; k++) {
System.out.print(R[k] + "\t");
}
}
}
测试效果如下:
排序前的数列为:
16 67 19 83 40 29 92 26 19 64
排序后的数列为:
16 19 19 26 29 40 64 67 83 92