双向冒泡排序算法是对经典冒泡排序算法的改进,它可以实现每一趟将最大的数“漂到”最上面,最小的数“沉到”最下面(或反过来)。
首先说下经典冒泡排序,它是第一趟从第一个数开始到倒数第二个数结束,每个数都与后一个数比较,若前者比后者大,二者就交换,第一趟结束后就将最大的那个书放到了最后一个数的位置。第二趟从第一个书开始到倒数第三个数结束,若前者比后者大,二者就交换,第二趟结束后就将最大的那个书放到了倒数第二个数的位置。如此循环下去,直到最后一趟结束就完成了排序。
public static void Sort(int[] arr){
int temp = 0;
for(int i=0;i<arr.length-1;i++){
for(int j=arr.length-1;j>i;j--){
if(arr[j]<arr[j-1]){
temp = arr[j-1];
arr[j-1] = arr[j];
arr[j] = temp;
}
}
}
}
双向冒泡排序是在经典冒泡排序的基础上扩充,它每一趟都将确定数组中两个位置上的数,从而将循环的趟数减少了一半。我自己写了两种写法,分别如下:
public static void Paixu1(int[] arr){
int temp = 0;
//从小到大排序
for(int i=0;i<arr.length/2;i++){
for(int j=i;j<arr.length-i-1;j++){
//对arr[i] arr[j] arr[arr.length-i-1]三个数排序
if(arr[i]>arr[j]){
temp = arr[j];
arr[j]=arr[i];
arr[i]=temp;
}
if(arr[i]>arr[arr.length-i-1]){
temp = arr[arr.length-i-1];
arr[arr.length-i-1]=arr[i];
arr[i]=temp;
temp = arr[arr.length-i-1];
arr[arr.length-i-1]=arr[j];
arr[j]=temp;
}
if(arr[j]>arr[arr.length-i-1]){
temp = arr[arr.length-i-1];
arr[arr.length-i-1]=arr[j];
arr[j]=temp;
}
}
}
}
public static void Paixu2(int[] arr){
//排序策略:冒泡排序,从左到右增序,从右到左降序
int temp=0;
for(int i=0;i<arr.length/2;i++){
//从左到右,每次确定下标为i位置上的数组元素
for(int j=i+1;j<=arr.length-1-i;j++){
if(arr[i]>arr[j]){
temp=arr[j];
arr[j]=arr[i];
arr[i]=temp;
}
}
//从右到左,每次确定下标为arr.length-i-1位置上的数组元素
for(int k=arr.length-i-1;k>=i;k--){
if(arr[k]>arr[arr.length-i-1]){
temp=arr[k];
arr[k]=arr[arr.length-i-1];
arr[arr.length-i-1]=temp;
}
}
}
}
第一种写法其实就是遍历数组中尚未排序的部分,这时的数组可以分成三部分,左部、中间、右部。其中左部和右部是已经排序好的部分,中间是尚未排序的部分,而我们每一趟的任务就是对中间这部分排序。每一趟从这部分的最左端遍历到最右端,用遍历到的数分别和这部分两端的两个数比较,以确定这部分两端的数是这次遍历到的两个最值,这样就实现了对数组的排序。这种写法好些,并且容易理解。
第二种写法是分别设定两个变量j和k,j从前向后遍历,k从后向前遍历,在每一趟内部j和k都同时遍历数组,并且和遍历到的数比较,以此来实现对数组的排序。这种写法容易被想到,但是写起来略复杂,且不太好理解其中的一些细节。