1. 游戏规则
我们会将排序代码放在类的sort()方法之中,该类还将包括辅助函数less()和exch()以及一个实例main()
大多数情况下,我们的排序代码只会通过两个方法操作数据:less()方法对元素进行比较,exch()方法将元素交换位置.exch()方法的实现很简单,通过Comparable()接口实现less()方法也不困难
排序算法的模板类
package 排序.初级排序算法;
/**
* 选择排序
*/
public class Selection {
/**
* 从小到达排序
* @param a
*/
public static void sort(Comparable[] a){
}
/**
* 判断v是否小于w
* @param v
* @param w
* @return
*/
private static boolean less(Comparable v, Comparable w){
return v.compareTo(w) < 0;
}
/**
* 交换两个元素的位置
* @param a
* @param i
* @param j
*/
private static void exch(Comparable[] a, int i, int j){
Comparable t = a[i]; a[i]=a[j]; a[j] = t;
}
/**
* 打印数组元素
* @param a
*/
private static void show(Comparable[] a){
//测试数组元素是否有序
for (int i = 1; i < a.length; i ++){
System.out.print(a[i]+ "");
}
System.out.println();
}
/**
* 测试是否已经从小到达排序
* @param a
* @return
*/
public static boolean isSorted(Comparable [] a){
//测试数组元素是否有序
for (int i = 1; i < a.length; i ++){
if (less(a[i],a[i-1])) return false;
}
return true;
}
public static void main(String[] args) {
}
}
2. 选择排序
一种最简单的排序算法是这样的:首先,找到数组中最小的那个元素,其次,将他和数组的第一个元素交换位置(如果第一个元素是最小元素那么他就和自己交换).再次,在剩下的元素中找到最小的元素,将他和数组中的第二个元素交换位置.如此反复,直到将整个数组排序.这种方法叫做选择排序,因为他在不断的选择剩余元素中的最小者
- 命题A:对于长度是N的数组,选择排序需要大约N的平方/2次比较和N次交换
总的来说,选择排序是一种很容易理解和实现的简单排序算法,他有两个很鲜明的特点
- 运行时间与输入无关
- 数据移动总是最少的
package 排序.初级排序算法;
/**
* 选择排序
*/
public class Selection {
/**
* 从小到达排序
* @param a
*/
public static void sort(Comparable[] a){
//将a按照升序排序
int N = a.length;//数组长度
for (int i = 0; i < N; i ++){
//将a[i]和a[i+1++N]中的最小元素交换
int min = i;//最小元素的索引
for (int j = i+1; j < N; j ++){
if (less(a[min], a[j])) min=j;
}
exch(a,i,min);
}
}
/**
* 判断v是否小于w
* @param v
* @param w
* @return
*/
private static boolean less(Comparable v, Comparable w){
return v.compareTo(w) < 0;
}
/**
* 交换两个元素的位置
* @param a
* @param i
* @param j
*/
private static void exch(Comparable[] a, int i, int j){
Comparable t = a[i]; a[i]=a[j]; a[j] = t;
}
/**
* 打印数组元素
* @param a
*/
private static void show(Comparable[] a){
//测试数组元素是否有序
for (int i = 1; i < a.length; i ++){
System.out.print(a[i]+ "");
}
System.out.println();
}
/**
* 测试是否已经从小到达排序
* @param a
* @return
*/
public static boolean isSorted(Comparable [] a){
//测试数组元素是否有序
for (int i = 1; i < a.length; i ++){
if (less(a[i],a[i-1])) return false;
}
return true;
}
public static void main(String[] args) {
}
}
3.插入排序
在计算机中为了给插入的元素腾出控件,我们需要将其余所有元素在插入之前都向右移动一位.这种算法叫做插入排序
与选择排序相同,当索引左边的所有元素都是有序的,但是他的最终位置还是为不能确定,为了给更小的元素腾出空间,他可能会被移动.但是索引到达数组右端的时候,数组排序就完成了.
- 命题B:
package 排序.初级排序算法;
/**
* 选择排序
*/
public class Insertion {
/**
* 从小到达排序
* @param a
*/
public static void sort(Comparable[] a){
//将a按照升序排序
int N = a.length;//数组长度
for (int i = 1; i < N; i ++){
//将a[i]插入到a[i-1]....0之中
for (int j = i; j > 0 && less(a[j],a[j-1]); j --){
exch(a,j,j-1);
}
}
}
/**
* 判断v是否小于w
* @param v
* @param w
* @return
*/
private static boolean less(Comparable v, Comparable w){
return v.compareTo(w) < 0;
}
/**
* 交换两个元素的位置
* @param a
* @param i
* @param j
*/
private static void exch(Comparable[] a, int i, int j){
Comparable t = a[i]; a[i]=a[j]; a[j] = t;
}
/**
* 打印数组元素
* @param a
*/
private static void show(Comparable[] a){
//测试数组元素是否有序
for (int i = 1; i < a.length; i ++){
System.out.print(a[i]+ "");
}
System.out.println();
}
/**
* 测试是否已经从小到达排序
* @param a
* @return
*/
public static boolean isSorted(Comparable [] a){
//测试数组元素是否有序
for (int i = 1; i < a.length; i ++){
if (less(a[i],a[i-1])) return false;
}
return true;
}
public static void main(String[] args) {
}
}
4. 希尔排序
对于大规模乱序数组插入排序很慢,因为他只会交换相邻的元素,因此元素只能 一点一点的从数组的一端移动到另一端.例如如果主键很小的元素正好在数组的尽头,要求将他挪到正确的位置就需要N-1次移动.
希尔排序为了加快速度简单的改进了插入排序,交换不相邻的元素以对数组的局部进行排序,并最终用插入排序将局部有序的数组排序
希尔排序的思想是使得数组中任意间隔为h的元素都是有序的.这样的数组称之为h有序数组.
换句话说,一个h有序数组就是h个互相独立的有序数组编织在一起组成的一个数组
在进行排序时,如果h很大,我们就能够将元素移动到很远的地方,为实现更小的h有序创造方便.**用这种方式对任意以1结尾的h序列,我们都能够将数组排序.**这就是希尔排序.下面算法的实现使用了序列1/2(3的k次方-1),从N/3开始递减至1.我们吧这个序列称之为递增序列.
实现希尔排序的一种方法是对于每个h,用插入排序jaignh个子数组独立的排序.但因为子数组是相互独立的,一个更简单的方法是在h-子数组中的每个元素交换到比他大的元素之前去(将比他大的元素向右移动一个).只需要在插入排序中将移动元素的距离将1改为h即可.这样希尔排序的实现就转化为了一个类似于插入排序但是使用不同增量的过程
希尔排序更高效的原因是他权衡了子数组的规模和有序性,排序之初,各个子数组都很短,排序之后子数组都是部分有序的,这两种情况很适合插入排序.子数组部分有序的程度取决于递增序列的选择.
package 排序.初级排序算法;
/**
* 选择排序
*/
public class Shell {
/**
* 从小到达排序
* @param a
*/
public static void sort(Comparable[] a){
//将a按照升序排序
int N = a.length;
int h = 1;
//只要最后能够使得
while (h < N/3) h=3*h+1;
while (h >=1){
for (int i = h; i < N; i ++){
for (int j = i; j >= h && less(a[j], a[j-h]); j-=h){
exch(a,j,j-h);
}
}
h/=3;
}
}
/**
* 判断v是否小于w
* @param v
* @param w
* @return
*/
private static boolean less(Comparable v, Comparable w){
return v.compareTo(w) < 0;
}
/**
* 交换两个元素的位置
* @param a
* @param i
* @param j
*/
private static void exch(Comparable[] a, int i, int j){
Comparable t = a[i]; a[i]=a[j]; a[j] = t;
}
/**
* 打印数组元素
* @param a
*/
private static void show(Comparable[] a){
//测试数组元素是否有序
for (int i = 1; i < a.length; i ++){
System.out.print(a[i]+ "");
}
System.out.println();
}
/**
* 测试是否已经从小到达排序
* @param a
* @return
*/
public static boolean isSorted(Comparable [] a){
//测试数组元素是否有序
for (int i = 1; i < a.length; i ++){
if (less(a[i],a[i-1])) return false;
}
return true;
}
public static void main(String[] args) {
}
}