1.冒泡排序
1.1 冒泡排序基本介绍
- 冒泡排序(Bubble Sorting)的基本思想是:通过对待排序序列从前向后(从下标较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前移向后部,就象水底下的气泡一样逐渐向上冒。
- 优化:
因为排序的过程中,各元素不断接近自己的位置,如果一趟比较下来没有进行过交换,就说明序列有序,因此要在排序过程中设置一个标志 flag 判断元素是否进行过交换。从而减少不必要的比较。(这里说的优化,可以在冒泡排序写好后,在进行)
- 升序(大数下沉,小数上浮)降序反之
1.2 冒泡排序图解
1.3 冒泡排序代码实现
1.3.1 实现数组升序
- 定义一个数组int[] arr = {12,15,34,2,1,6}
- 加入flag进行优化,减少重复的排序
public static void main(String[] args) {
int[] arr = {12,15,34,2,1,6};
long a = System.currentTimeMillis();
int[] arr2 = new int[80000];
for (int i = 0; i < 80000; i++) {
arr2[i] = (int)(Math.random()*80000);
}
sort(arr2);
long b = System.currentTimeMillis();
System.out.println("程序运行时间:"+(b-a));
}
public static void sort(int[] arr){
boolean flag = false; //flag初始化为false
int temp = 0; //初始化一个整数temp,用来临时保存arr[j]
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]){ //前一个比后一个大就需要前后交换
flag = true;
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
if (!flag){ //判断flag是否为true,true代表已经交换过,如果是true直接结束循环
break;
}else {
flag = false; //将flag设置为false方便下一次循环使用
}
}
}
- 排序后运行结果
- 冒泡排序后:[1, 2, 6, 12, 15, 34]
1.3.2 加入一个随机数组测试排序运行的时间(性能)
- 设置一个数组 int[] arr2 = new int[80000]
- 随机获取80000个数 for (int i = 0; i < 80000; i++) { arr2[i] = (int)(Math.random()*80000); }
- 使用System.currentTimeMillis()来获取时间,单位毫秒
long a = System.currentTimeMillis();
int[] arr2 = new int[80000];
for (int i = 0; i < 80000; i++) {
arr2[i] = (int)(Math.random()*80000);
}
sort(arr2);
long b = System.currentTimeMillis();
System.out.println("程序运行时间:"+(b-a));
- 运行结果
程序运行时间:9788 (毫秒)
2.选择排序
2.1 选择排序介绍
- 选择式排序也属于内部排序法,是从欲排序的数据中,按指定的规则选出某一元素,再依规定交换位置后达到排序的目的。
- 前后两两比较,每一次遍历和最小值交换(升序)
2.2 选择排序图解
2.3 选择排序代码实现
- 定义数据 int[] arr = {23,5,47,78,3,2,1}
public static void main(String[] args) {
int[] arr = {23,5,47,78,3,2,1};
for (int i = 0; i < arr.length-1; i++) {
int minIndex = i;
int min = arr[i];
for (int j = i+1; j < arr.length; j++) { //最后一个数也要比较
if (min>arr[j]){
min = arr[j]; //重置min
minIndex = j; //重置minIndex
}
}
if (minIndex!=i){ //如果不重复就交换,和arr[0]交换
arr[minIndex] = arr[i];
arr[i] = min;
}
}
System.out.println(Arrays.toString(arr));
}
- 运行结果
- [1, 2, 3, 5, 23, 47, 78]
2.4 测试选择排序的性能
- 设置一个数组 int[] arr2 = new int[80000]
- 随机获取80000个数 for (int i = 0; i < 80000; i++) { arr2[i] = (int)(Math.random()*80000); }
- 使用System.currentTimeMillis()来获取时间,单位毫秒
long a = System.currentTimeMillis();
int[] arr2 = new int[80000];
for (int i = 0; i < 80000; i++) {
arr2[i] = (int)(Math.random()*80000);
}
sort(arr2);
long b = System.currentTimeMillis();
System.out.println("程序运行时间:"+(b-a));
程序运行时间:2018 (毫秒)
3.插入排序
3.1 插入排序介绍
- 插入式排序属于内部排序法,是对于欲排序的元素以插入的方式找寻该元素的适当位置,以达到排序的目的
- 第一个数永远看成一个有序的,不动,从第二个数开始比较
3.2 插入排序图解
3.3 插入排序代码实现
- 定义数组 int[] arr = {45,5,3,456,4,2,6}
public static void main(String[] args) {
int[] arr = {45,5,3,456,4,2,6};
for (int i = 1; i < arr.length; i++) { //从第二个数开始
int insertVal = arr[i];
int insertIndex = i - 1; //每次和前一个开始
while (insertIndex >= 0 && insertVal < arr[insertIndex]){ // insertVal < arr[insertIndex]表示升序
arr[insertIndex+1] = arr[insertIndex]; //先占位置
insertIndex--;
}
if (insertIndex+1 != i){
arr[insertIndex+1] = insertVal; //插入位置
}
}
System.out.println(Arrays.toString(arr));
}
- 运行结果
- [2, 3, 4, 5, 6, 45, 456]
3.4 插入排序测试性能
- 设置一个数组 int[] arr2 = new int[80000]
- 随机获取80000个数 for (int i = 0; i < 80000; i++) { arr2[i] = (int)(Math.random()*80000); }
- 使用System.currentTimeMillis()来获取时间,单位毫秒
long a = System.currentTimeMillis();
int[] arr = new int[80000];
for (int i = 0; i < 80000; i++) {
arr[i] = (int)(Math.random()*80000);
}
sort(arr);
long b = System.currentTimeMillis();
System.out.println("程序运行时间:"+(b-a));
- 运行时间
程序运行时间:640 (毫秒)
4.总结
插入排序在寻找插入位置时,需要对数组元素进行整体挪位,所以效率比选择排序稍低。从以上三种测试的运行结果看,插入排序是时间最优。