冒泡排序,选择排序和插入排序
这两天的《算法》进入排序的学习后,遇到了一些问题,下面是我自己总结的理解:
冒泡排序:
两两相比较遍历数组不断以两两交换的方式找到最值(最大或最小),再从循环中剔除该最值缩小遍历范围继续一次从头至尾的遍历,循环很多次至最终排序完成。
选择排序:
以一个变量存储下表索引,同冒泡排序一样的两两相比较,但不交换,而是不断用变量存储极值(大或小)的索引,直至找到最值后与边界元素外循环a.[i]交换,然后i自增剔除该最值缩小遍历范围继续用该方法遍历,循环很多次至最终排序完成。
插入排序:
以一个数组元素为标志(算法中一般从边界开始),以一个方向依次为反方向的相邻元素相比较,若比较结果符合排序要求,则该标志前进(外循环自增一),继续按照方向与下一个进行比较;若结果不符合排序要求,则进入内循环,找出的这个不符元素与相邻元素交换后退,然后继续后退与相邻元素比较(再交换),直至后退至该元素的位置符合排序要求,然后退出内循环,外循环自增一标志继续前进。这样的外循环一次遍历之后,排序完成。如果数组本身是部分有序的,那么排序时间将大大减少。
总结:
选择排序是冒泡排序的优化,虽然两种比较次数是一样的,但是选择排序减少了交换次数,缩减了排序时间
插入排序相比上述排序,以精妙的算法极大优化了比较次数,因此在《算法》p160中定论:插入排序平均比选择排序快一倍。但这并不是插入排序的最优解,在书中p158中有提到,因为内循环中,找到不符元素后,采用了冒泡排序的思想不断交换,可以进一步进行优化,把比待插入值大的值均向后移动以为而不是操作待差值两两交换,最后存在两个相同的值,该值是比待差值大的最接近的值,将待差值与上述值原位置值变为待差值完成插入,就能进一步缩减排序时间,如下:
交换式:
public static void insertSort(int[] arr) { int insertVal = 0; int insertIndex = 0; int temp=0; //使用for 循环来把代码简化 for(int i = 1; i < arr.length; i++) { //定义待插入的数 insertVal = arr[i]; insertIndex = i - 1; // 即arr[1]的前面这个数的下标 // 给insertVal 找到插入的位置并交换 for(int j=insertIndex;j >= 0;j--){ if (insertVal < arr[j]) { temp = arr[j]; arr[j]=arr[j + 1]; arr[j + 1]=temp; } } System.out.println("第"+i+"轮插入"); System.out.println(Arrays.toString(arr)); } }
移位式:
public static void insertSort(int[] arr) { int insertVal = 0; int insertIndex = 0; //使用for 循环来把代码简化 for(int i = 1; i < arr.length; i++) { //定义待插入的数 insertVal = arr[i]; insertIndex = i - 1; // 即arr[1]的前面这个数的下标 // 给insertVal 找到插入的位置 while (insertIndex >= 0 && insertVal < arr[insertIndex]) { arr[insertIndex + 1] = arr[insertIndex];// arr[insertIndex] insertIndex--; } //这里我们判断是否需要赋值 if(insertIndex + 1 != i) { arr[insertIndex + 1] = insertVal; } System.out.println("第"+i+"轮插入"); System.out.println(Arrays.toString(arr));
}
}
上述三种算法都无法解决大型数组问题,或者性能很差
以上排序的源码百度一下到处都有,注意理解对应就好