排序算法中最入门的一个排序算法就是冒泡排序,面试中经常会考到的一个基础题目。那么什么是冒泡排序呢?以及冒泡排序算法的基本原理是什么呢?
本文会一 一解答。
1,冒泡排序及其原理
原理:比较两个相邻的元素,将值大的元素交换至右端。
思路:第一趟,依次比较相邻的两个数,将小数放在前面,大数放在后面。重复第一趟步骤,每次从数组的第一个元素从头开始,直至全部排序完成。
2,示例
(本示例摘自http://www.cnblogs.com/shen-hua/p/5422676.html)
举例说明:要排序数组:int[] arr={6,3,8,2,9,1};
第一趟排序:
第一次排序:6和3比较,6大于3,交换位置: 3 6 8 2 9 1
第二次排序:6和8比较,6小于8,不交换位置:3 6 8 2 9 1
第三次排序:8和2比较,8大于2,交换位置: 3 6 2 8 9 1
第四次排序:8和9比较,8小于9,不交换位置:3 6 2 8 9 1
第五次排序:9和1比较:9大于1,交换位置: 3 6 2 8 1 9
第一趟总共进行了5次比较, 排序结果: 3 6 2 8 1 9
第二趟排序:
第一次排序:3和6比较,3小于6,不交换位置:3 6 2 8 1 9
第二次排序:6和2比较,6大于2,交换位置: 3 2 6 8 1 9
第三次排序:6和8比较,6大于8,不交换位置:3 2 6 8 1 9
第四次排序:8和1比较,8大于1,交换位置: 3 2 6 1 8 9
第二趟总共进行了4次比较, 排序结果: 3 2 6 1 8 9
第三趟排序:
第一次排序:3和2比较,3大于2,交换位置: 2 3 6 1 8 9
第二次排序:3和6比较,3小于6,不交换位置:2 3 6 1 8 9
第三次排序:6和1比较,6大于1,交换位置: 2 3 1 6 8 9
第二趟总共进行了3次比较, 排序结果: 2 3 1 6 8 9
第四趟排序:
第一次排序:2和3比较,2小于3,不交换位置:2 3 1 6 8 9
第二次排序:3和1比较,3大于1,交换位置: 2 1 3 6 8 9
第二趟总共进行了2次比较, 排序结果: 2 1 3 6 8 9
第五趟排序:
第一次排序:2和1比较,2大于1,交换位置: 1 2 3 6 8 9
第二趟总共进行了1次比较, 排序结果: 1 2 3 6 8 9
最终结果:1 2 3 6 8 9
冒泡排序的优点:每进行一趟排序,就会少比较一次,因为每进行一趟排序都会找出一个较大值。如上例:第一趟比较之后,排在最后的一个数一定是最大的一个数,第二趟排序的时候,只需要比较除了最后一个数以外的其他的数,同样也能找出一个最大的数排在参与第二趟比较的数后面,第三趟比较的时候,只需要比较除了最后两个数以外的其他的数,以此类推……也就是说,每进行一趟比较,每一趟少比较一次,一定程度上减少了算法的量。
3,实现代码
Bubble.java
package sort;
public class Bubble {
public static void main(String[] args) {
int[] a={2,1,5,3,8,2,0};
// sort1(a);
// sort2(a);
sort3(a);
for(int i:a){
System.out.println(i);
}
}
/**
* 没有做任何优化的算法
* 外层循环为一共需要多少趟排序,内层循环为每一趟需要多少次排序
* @param a
*/
public static void sort1(int[] a){
int length=a.length;
for(int i=0;i<length-1;i++){
for(int j=0;j<length-i-1;j++){
if(a[j]>a[j+1]){
int temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
}
/**
* 优化的排序算法
* 优化的地方有两点:
* 1,每趟排序之后,最后一个数字一定是最大值
* 2,根据这一趟是否有数值交换就可以判断是否已经排序完毕
* @param a
*/
public static void sort2(int[] a){
boolean changed=true;
int num=a.length-1;
while(changed){
changed=false;
for(int i=0;i<num;i++){
if(a[i]>a[i+1]){
int temp=a[i];
a[i]=a[i+1];
a[i+1]=temp;
changed=true;
}
}
num--;
}
}
/**
* 优化的排序算法
* 这种冒泡算法的优势在于处理的数组满足下面的情况:
* 数组后一部分可能大于前一部分,因此后部分不需要进行排序
* 优化的地方有两点:
* 1,每趟排序之后,记录最后的交换位置,下次排序的范围就在这个标记的位置之前
* 2,每趟排序都要将flag置零,排序的终止条件就是flag=0的时候
*
* @param a
*/
public static void sort3(int[] a){
int num=a.length-1;
int flag=num;
while(flag>0){
int k=flag;
flag=0;
for(int i=0;i<k;i++){
if(a[i]>a[i+1]){
int temp=a[i];
a[i]=a[i+1];
a[i+1]=temp;
flag=i;
}
}
}
}
}
结论:
1,第一种排序算法,冒泡排序法的时间复杂度O(N^2),因为每一趟都要进行比较
2,第二种排序算法和第三种算法,冒泡排序法的时间复杂度取决于输入的数组。最优时间复杂度为O(N),最坏时间复杂度为O(N^2)。