一)算法介绍
冒泡排序是一种入门级的稳定排序算法。
该名称的由来是因为越大的元素会经过交换,慢慢“浮”到顶端。
稳定排序:如果a原本在b前面,而a=b,排序之后a仍然在b的前面;
二)算法原理
基本原理:比较相邻的两个元素。如果第一个比第二个大,就交换他们两个。对每一对相邻的元素作同样的工作,从开始第一对到结尾的最后一对。最后的元素应该会是最大的数。
算法步骤图解(从head到last,依次从小到大排列)
源数据:
第一遍排序:从head开始比较,5<6,5和6位置不变,再比较6>3,交换6和3的位置,再比较6>1,交换6和1的位置,再比较6<8,6和8位置不变,再比较8>7,交换8和7的位置,再比较8>2,交换8和2的位置,再比较8>4,交换8和4的位置,8是最大的数,排列再最后一位。
第二遍排序:从head开始比较,5>3,交换5和3的位置,再比较5>1,交换5和1的位置,再比较5<6,5和6位置不变,再比较6<7,6和7位置不变,再比较7>2,交换7和2的位置,再比较7>4,交换7和4的位置,不需要和8比较了。
第三遍排序:从head开始比较,3>1,交换3和1的位置,再比较3<5,3和5位置不变,再比较5<6,5和6位置不变,再比较6>2,交换6和2的位置,再比较6>4,交换6和4的位置,不需要和78比较了。
第四遍排序:从head开始比较,1<3,1和3位置不变,再比较3<5,3和5位置不变,再比较5>2,交换5和2的位置,再比较5>4,交换5和4的位置,不需要和678比较了。
第五遍排序:从head开始比较,1<3,1和3位置不变,再比较3>2,交换3和2的位置,再比较3<4,3和4位置不变,不需要和5678比较了。排序已完成。
算法复杂度:
最差情况:T(n) = O(n^2)
最好情况:T(n) = O(n),在所有元素已经排好序的情况(只需要比较一次)
// n=100;
// O(n)含义
for(i=0;i<100;i++){
}
// O(n^2)含义
for(i=0;i<100;i++) {
for(i=0;i<100;i++){
}
}
三)算法源码
第一种方式:冒泡排序每比较完一遍,就可以确定最大数的位置,最大数会排列到最后面一位,下次不需要再重复比较,所以每循环一遍,次数就需要减1。
public static int[] bubbleSort(int[] nums) {
if (nums == null) {
return null;
}
for (int i = 0; i < nums.length; i++) {
for (int j = 0; j < nums.length - 1 - i; j++) {
if (nums[j] > nums[j+1]) {
int temp = nums[j];
nums[j] = nums[j+1];
nums[j+1] = temp;
}
}
}
return nums;
}
第二种方式:在第一种方式基础上,由于比较的时候,有一些元素已经是有序的(有序元素可以不需要再比较),可以记录上次比较的位置,在进行下一轮比较的时候,到达该位置时,就可以不需要比较了(因为已经有序了,重复比较没意义)。
public static int[] bubbleSortMax(int[] nums) {
if (nums == null) {
return null;
}
int border = nums.length - 1;
int lastIndex = 0; // 记录内循环的下标
for (int i = 0; i < nums.length; i++) {
boolean isSorted = true; // 初始化
for (int j = 0; j < border; j++) { // 如果发现后面是有序的,可以缩小每一轮比较的边界
if (nums[j] > nums[j+1]) {
int temp = nums[j]; // 声明一个临时变量存储
nums[j] = nums[j+1];
nums[j+1] = temp;
isSorted = false; // 记录是否已经排序
lastIndex = j; // 记录本次比较的边界
}
}
// 如果已经排序完,就跳出循环
if (isSorted) {
break;
}
border = lastIndex; // 记录最后一个排序的边界, 因为边界后面都是已经排好序的
}
return nums;
}
识别二维码关注个人微信公众号
本章完结,待续,欢迎转载!
本文说明:该文章属于原创,如需转载,请标明文章转载来源!