一、算法描述
- 它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。
- 这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端一样,故名“冒泡排序”。
二、算法原理
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
三、时间复杂度
若文件的初始状态是正序的,一趟扫描即可完成排序。所需的关键字比较次数 C和记录移动次数M 均达到最小值:
(Cmin = n-1、Mmin = 0)
所以,冒泡排序最好的时间复杂度为 O(n) 。
四、算法实现
//冒泡排序
public static void main(String[] args) {
int[] arr ={8,9,5,4,-9,99,0,68,51,44};
for (int i = 1; i <=arr.length-1 ; i++) {
for (int j = 0; j <=arr.length-1-i ; j++) {
if(arr[j]>arr[j+1]){
int num=arr[j];
arr[j]=arr[j+1];
arr[j+1]=num;
}
}
}
//输出数组的每个元素
for (int a:arr
) {
System.out.print(a+"\t");//-9 0 4 5 8 9 44 51 68 99
}
}
下面的代码是重点,请记忆此代码
int[] arr ={1,5,6,8,7};
for (int i = 0; i <arr.length-1 ; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j]>arr[j+1]){
int num=arr[j];
arr[j]=arr[j+1];
arr[j+1]=num;
}
}
}
System.out.println(Arrays.toString(arr));//[1, 5, 6, 7, 8]
总结:
外层的遍历轮数为数组长度-1
内层的最大比较次数为数组长度-1
五、总结
冒泡排序算法:相邻两个数相互比较,外层一轮结束后,最大值到右边。
int[] Arr=[5,4,3,2,1];
当i=0;
外层循环轮数 | 数组元素变化 | 前数下标范围 | 后数下标范围 | 比较次数 |
---|---|---|---|---|
外层第一轮 | 4,3,2,1,5 | 0,len-2 | 1,len-1 | 4 |
外层第二轮 | 3,2,1,4,5 | 0,len-3 | 1,len-2 | 3 |
外层第三轮 | 2,1,3,4,5 | 0,len-4 | 1,len-3 | 2 |
外层第四轮 | 1,2,3,4,5 | 0 | 1 | 1 |
len-1趟 | 0 | len-i-1 |
外层的遍历轮数为数组长度-1
当i=0时,
外层循环轮数下标的取值范围:从0到len-2(0到3,4次)
内层循环比较次数下标的取值范围:从0到len-2-i
当i=1时,
外层循环轮数下标的取值范围:从1到len-1(1到4,4次)
内层循环比较次数下标的取值范围:从0到len-1-i