什么是排序?
排序是按照某种顺序(升序或降序)排列序列元素的一种算法。排序的输出是输入的排列或重新排列。
例如:还记得上学时的第一次出操吗?先开始都是毫无顺序的站在自己班级的一排上(排序的输入),等到老师来了,就会让我们按照个头高低顺序排列(对排序的输入采用升序或降序)。
如何按个头从低到高(升序)或从高到低(降序)的排列学生?
1. 学生们自己和后面同学比较,谁个头高站在后面,逐个相互比较。最后同学们由低到高站在1列上(顺便说一句,我上操都站在前排,呜呜~~~~)。
2. 老师随便找出来一个同学站在最前排,然后逐一的让其他同学和他比较,谁个头更低些,站在最前排位置上。之后每排都按这种方式排列。
让个头高低不同的同学们由低到高的顺序站在一列上就是排序,如何排序学生就是算法。
对于算法的概念还有些模糊的同学可以参考我的博客:数据结构与算法
什么是冒泡排序?
冒泡排序是一种排序算法(就如第1种排列学生的方法一样)。其基本思想是迭代地对输入序列中的第一个元素到最后一个元素进行两两比较,当需要时交换这两个元素(位置)。该过程持续迭代直到在一趟排序过程中不需要交换操作为止。冒泡排序得名于键值较小的元素如同“气泡”一样逐渐漂浮到序列的顶端。
例如:给定这样一个顺序: 6 8 1 4 5 3 7 2 9
相邻两个数之间相互比较。
第1次排序: 6 1 4 5 3 7 2 8 9
第2次排序: 1 4 5 3 6 2 7 8 9
第3次排序: 1 4 3 5 2 6 7 8 9
第4次排序: 1 3 4 2 5 6 7 8 9
第5次排序: 1 3 2 4 5 6 7 8 9
第6次排序: 1 2 3 4 5 6 7 8 9
第7次排序: 1 2 3 4 5 6 7 8 9
第8次排序: 1 2 3 4 5 6 7 8 9
在这里我们要考虑到最坏的情况,9个数最坏的情况是比较(9-1)次,这是相邻比较带来的结果。由此可以得出n个数最坏的情况是比较(n-1)次。同学们可以自己编写一列数测试一下。
细心的同学会发现:从第六次开始开始其实排序已经完成了。为什么还有7、8两次排序呢?其实这就归功于算法的神奇之处,下面我就编写两套冒泡排序算法供大家比较。看看好的算法能带给我们什么。
上代码:
首先在控制台输入要排序的一列数:
请输入预计的元素个数:
9
请输入元素
6 8 1 4 5 3 7 2 9
1. 未改进之间的冒泡排序
public class BubbleSort {
public static void main(String[] args) {
int n;
Scanner scanner = new Scanner(System.in);
System.out.println("请输入预计的元素个数:");
n = scanner.nextInt();
System.out.println("请输入元素");
int[] array = new int[n];
for (int i = 0; i < array.length; i++) {
array[i] = scanner.nextInt();
}
bubbleSort(array);
afterSort(array);
}
//未改进之间的冒泡排序
static void bubbleSort(int[] array){
//最坏情况下需要比较的次数 数组元素的个数-1
for (int i = 1; i < array.length; i++) {
//需要比较的元素
for (int j = 0; j < array.length - i; j++) {
/**
* 迭代地对输入序列中的第一个元素到最后一个元素进行两两比较。
* 注意:这是冒泡排序的精髓,将数值较小的元素如同“气泡”一样“逐渐”漂浮到序列的顶端。
* 也就是说:元素的排列顺序与数组的下标的排列顺序是一致的,都是从小到大排列。
* 顺便提一句:一连串的数据叫做序列。例如:array中的数据就是一串序列。
*/
if(array[j]>array[j+1]){
//定义一个临时存放区,方便交换数组元素
int temp = array[j+1];
//交换数据
array[j+1] = array[j];
array[j] = temp;
}
}
System.out.print("这是第"+i+"次排列:");
for (int j = 0; j < array.length; j++) {
System.out.print(array[j] + " ");
if(j==array.length-1){
System.out.println();
}
}
}
}
//用于表示每次排序之后的结果
static void restOfEach(int[] array,int i){
System.out.print("这是第"+i+"次排列:");
for (int j = 0; j < array.length; j++) {
System.out.print(array[j] + " ");
if(j==array.length-1){
System.out.println();
}
}
}
//排序完成的结果
static void afterSort(int[] array){
System.out.print("排序后的数组元素:");
for (int i = 0; i < array.length; i++) {
if(i<array.length-1){
System.out.print(array[i] + ",");
}else{
System.out.print(array[i]);
}
}
}
执行后得到的结果:
这是第1次排列:6 1 4 5 3 7 2 8 9
这是第2次排列:1 4 5 3 6 2 7 8 9
这是第3次排列:1 4 3 5 2 6 7 8 9
这是第4次排列:1 3 4 2 5 6 7 8 9
这是第5次排列:1 3 2 4 5 6 7 8 9
这是第6次排列:1 2 3 4 5 6 7 8 9
这是第7次排列:1 2 3 4 5 6 7 8 9
这是第8次排列:1 2 3 4 5 6 7 8 9
排序后的数组元素:1,2,3,4,5,6,7,8,9
2. 改进之后的冒泡排序
//改进之后的冒泡排序
static void bubbleSortImprove(int[] array){
/**
* swapped 用于标记排序是否完成,这是改进之后的精髓所在。
*/
boolean swapped = true;
//注意:这层循环需要判断swapped
for (int i = 1; i < array.length && swapped; i++) {
swapped = false;
for (int j = 0; j < array.length-i; j++) {
/**
* 当程序走到这里时,进入判断区,是否还有未排列的数据。
* 如果已经排序完了,告诉swapped,喂!你们排序结束了,不给你们门票(true),别再来了。
* 这时swapped = false,循环结束
*/
if(array[j]>array[j+1]){
int temp = array[j+1];
array[j+1] = array[j];
array[j] = temp;
swapped = true;
}
}
restOfEach(array, i);
}
}
执行后得到的结果
这是第1次排列:6 1 4 5 3 7 2 8 9
这是第2次排列:1 4 5 3 6 2 7 8 9
这是第3次排列:1 4 3 5 2 6 7 8 9
这是第4次排列:1 3 4 2 5 6 7 8 9
这是第5次排列:1 3 2 4 5 6 7 8 9
这是第6次排列:1 2 3 4 5 6 7 8 9
这是第7次排列:1 2 3 4 5 6 7 8 9
排序后的数组元素:1,2,3,4,5,6,7,8,9
总结:
我们看到,未改进之前的冒泡排序需要进行 8 次排序,而改进之后的冒泡排序进行 7 次排序。别看仅仅相差一次排序,差了一点性能而已。对于大型的项目动辄几百万行的代码来说,这样小的性能相加起来就会形成巨大的性能下降,这就是我们要学习算法的原因所在。
希望大家在下方留言,指出不足之处,共同进步。