冒泡排序
package 排序算法;
import java.util.Arrays;
import org.junit.Test;
/*
* 冒泡排序:
*从 arr[0]起,前一个依次和后一个比,谁大谁放后面,直到最后一个元素,确定最大的
*从 arr[0]起,前一个依次和后一个比,谁大谁放后面,直到次后个元素,确定第二二的
*从 arr[0]起,前一个依次和后一个比,谁大谁放后面,直到次次后个元素,确定第三大的
*..........
* .........
*/
public class BubblingSort {
/*
* 冒泡排序算法
*/
@Test
public void sort() {
//生成长度20的随机数组
int [] arr=new int[20];
for(int i=0;i<arr.length;i++) {
arr[i]=(int)(Math.random()*100+1);
}
//记录交换次数
int count=0;
//外层for循环
for (int i=0;i<arr.length;i++) {
//前后两数比较,满足条件则交换
for (int j=1;j<arr.length-i;j++) {
if(arr[j-1]>arr[j]) {
arr[j]=arr[j-1]+arr[j];
arr[j-1]=arr[j]-arr[j-1];
arr[j]=arr[j]-arr[j-1];
count++;
}
}
}
System.out.println("排序后的数组:"+Arrays.toString(arr)+"\n 排序次数:"+count);
}
}
运行结果
排序后的数组:[7, 8, 11, 14, 16, 17, 19, 20, 25, 30, 50, 52, 55, 61, 64, 66, 68, 93, 98, 100]
排序次数:73
优化后的冒泡排序
package 排序算法;
import java.util.Arrays;
import org.junit.Test;
public class OptimizeBubblingSort {
/*
* 冒泡排序算法
*/
@Test
public void sort() {
//生成长度20的随机数组
int [] arr=new int[20];
for(int i=0;i<arr.length;i++) {
arr[i]=(int)(Math.random()*100+1);
}
//记录交换次数
int count=0;
//外层for循环
for (int i=0;i<arr.length;i++) {
//记录下最大数的下标,默认当前序列尾部元素最大
int index=arr.length-1-i;
//查找当前序列真实的最大的数下标
for (int j=1;j<arr.length-i;j++) {
if(arr[j-1]>arr[index]) {
index=j-1;
}
}
//如果不是尾部元素最大,则交换并记录交换次数
if(index!=arr.length-1-i) {
arr[arr.length-1-i]=arr[index]+arr[arr.length-1-i];
arr[index]=arr[arr.length-1-i]-arr[index];
arr[arr.length-1-i]=arr[arr.length-1-i]-arr[index];
count++;
}
}
System.out.println("排序后的数组:"+Arrays.toString(arr)+"\n 排序次数:"+count);
}
}
运行结果
排序后的数组:[12, 16, 18, 30, 32, 35, 43, 46, 50, 53, 56, 56, 58, 67, 67, 75, 93, 94, 94, 98]
排序次数:15
实质上优化过后的冒泡排序就是选择排序了。
选择排序
package 排序算法;
import java.util.Arrays;
import org.junit.Test;
/*
* 选择排序:
* arr[0]依次和arr[1]...arr[arr.length-1]比较,记录下最小的数,与arr[0]交换位置
* arr[1]依次和arr[2]...arr[arr.length-1]比较,记录下最小的数,与arr[1]交换位置
* arr[2]依次和arr[3]...arr[arr.length-1]比较,记录下最小的数,与arr[2]交换位置
* .........
*
* .........
*/
public class SelectionSort {
/*
* 选择排序算法
*/
@Test
public void sort() {
//生成一个长度为20的随机数组
int [] arr=new int[20];
for(int i=0;i<arr.length;i++) {
arr[i]=(int)(Math.random()*100+1);
}
//记录交换次数
int count=0;
//外层循环
for(int i=0;i<arr.length;i++) {
//记录最小的元素下标,默认头部元素最小
int index=i;
//查找当前序列中最小的元素下标
for(int j=i+1;j<arr.length;j++) {
if(arr[j]<arr[index]) {
index=j;
}
}
//如果不是头部元素最小,则交换并记录交换次数
if(index!=i) {
arr[index]=arr[index]+arr[i];
arr[i]=arr[index]-arr[i];
arr[index]=arr[index]-arr[i];
count++;
}
}
System.out.println("排序后的数组:"+Arrays.toString(arr)+"\n 排序次数:"+count);
}
}
运行结果
排序后的数组:[3, 16, 16, 17, 27, 27, 28, 30, 36, 37, 43, 43, 46, 47, 49, 56, 60, 73, 89, 92]
排序次数:17
对比总结
1、冒泡排序是相邻两个数比,这两个比较的数一致在向右移动,选择排序是固定一个位置的数和其后的数比,只
有一个数在移动。优化过后的冒泡排序实际上就是选择排序。
2、对于数组从小到大排序
冒泡排序第X趟下来确定第X大的元素,放在数组的倒数第X个位置
选择排序第X趟下来确定第X小的元素,放在数组的顺数第X个位置
冒泡排序一趟会交换很多次,是稳定的。
选择排序一趟只交换一次,是不稳定的。
稳定和不稳定:
比如对于数组5,6,2,8,1
原本5,6顺序符合要求,但选择排序第一趟下来,2和5交换位置,5,6的从小到大顺序比打乱这就是不稳定。
而对于选择排序,则不会出现打乱已有的满足条件的顺序,是稳定的。
稳不稳定其实取决于一趟交换几次,交换一次肯定不稳定,优化过后的冒泡排序交换一次,不稳定。