通常人们整理桥牌的方法是一张一张的来,将每一张牌插入到其他已经有序的牌中的适当位置。在计算机的实现中,为了给要插入的元素腾出空间,我们需要将其余所有元素在插入之前都向右移动一位。这种算法叫做插入排序。
插入排序所需的时间取决于输入中元素的初始顺序。
以下是实现代码:
public class Insertion
{
static int compareCount = 0;
static int changeCount = 0;
static int loopCount = 0;
//对元素进行比较
public static boolean less(Comparable v, Comparable w){
compareCount++;
return v.compareTo(w) < 0;
}
public static void exch(Comparable[] a, int i, int j)
{
Comparable t = a[i];
a[i] = a[j];
a[j] = t;
changeCount++;
}
//在单行中打印数组
public static void show(Comparable[] a)
{
for (int i = 0; i < a.length; i++)
{
if (i == a.length - 1)
System.out.print(a[i]);
else
System.out.print(a[i] + ",");
}
}
//测试数组元素是否有序
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 sort(Comparable[] a)
{
//将a[]按升序排序
int N = a.length;
int d = 0;
for (int i = 0; i < N; i++)
{ //将a[]按升序排列
for (int j = i; j > 0 && less(a[j], a[j-1]); j--){
exch(a, j, j - 1);
System.out.printf("第%d次交换,交换的位置索引:%d \t[", ++d, j);
show(a);
System.out.println("]");
}
}
}
public static void main(String[] args){
Integer[] a = {4,5,2,9,6,3,7,1,8,0};
System.out.print("\t\t\t\t\t\t\t[");
show(a);
System.out.print("]\n");
sort(a);
assert isSorted(a);
System.out.printf("一共交换了:%s次,比较了:%s次 \n", changeCount, compareCount);
}
}
输出结果是这样的: (红色为待交换位置索引)
原数组 [4,5,2,9,6,3,7,1,8,0]
第1次交换,交换的位置索引:2 [4,2,5,9,6,3,7,1,8,0]
第2次交换,交换的位置索引:1 [2,4,5,9,6,3,7,1,8,0]
第3次交换,交换的位置索引:4 [2,4,5,6,9,3,7,1,8,0]
第4次交换,交换的位置索引:5 [2,4,5,6,3,9,7,1,8,0]
第5次交换,交换的位置索引:4 [2,4,5,3,6,9,7,1,8,0]
第6次交换,交换的位置索引:3 [2,4,3,5,6,9,7,1,8,0]
第7次交换,交换的位置索引:2 [2,3,4,5,6,9,7,1,8,0]
第8次交换,交换的位置索引:6 [2,3,4,5,6,7,9,1,8,0]
第9次交换,交换的位置索引:7 [2,3,4,5,6,7,1,9,8,0]
第10次交换,交换的位置索引:6 [2,3,4,5,6,1,7,9,8,0]
第11次交换,交换的位置索引:5 [2,3,4,5,1,6,7,9,8,0]
第12次交换,交换的位置索引:4 [2,3,4,1,5,6,7,9,8,0]
第13次交换,交换的位置索引:3 [2,3,1,4,5,6,7,9,8,0]
第14次交换,交换的位置索引:2 [2,1,3,4,5,6,7,9,8,0]
第15次交换,交换的位置索引:1 [1,2,3,4,5,6,7,9,8,0]
第16次交换,交换的位置索引:8 [1,2,3,4,5,6,7,8,9,0]
第17次交换,交换的位置索引:9 [1,2,3,4,5,6,7,8,0,9]
第18次交换,交换的位置索引:8 [1,2,3,4,5,6,7,0,8,9]
第19次交换,交换的位置索引:7 [1,2,3,4,5,6,0,7,8,9]
第20次交换,交换的位置索引:6 [1,2,3,4,5,0,6,7,8,9]
第21次交换,交换的位置索引:5 [1,2,3,4,0,5,6,7,8,9]
第22次交换,交换的位置索引:4 [1,2,3,0,4,5,6,7,8,9]
第23次交换,交换的位置索引:3 [1,2,0,3,4,5,6,7,8,9]
第24次交换,交换的位置索引:2 [1,0,2,3,4,5,6,7,8,9]
第25次交换,交换的位置索引:1 [0,1,2,3,4,5,6,7,8,9]
一共交换了:25次,比较了:31次
以上内容摘抄自《算法 第四版》
其实最开始我也觉得有点懵,因为在我看来,整理桥牌就两步,第一:拿出要整理的牌,第二:插入对应的位置。
哈哈,其实漏了一步最重要的,就是比较。
例如
初始顺序是 2 4 5 3 9
第一次所需排序的是3,于是将3和之前的位置依次对比,如果小于前一个位置,则交换位置,重新比较。
第一次, 3 和 5 对比,5 比 3 大,所以 5 和 3 交换位置,最终结果 2 4 3 5 9。
第二次, 3 和 4 对比,4 比 3 大,所以 4 和 3 交换位置,最终结果 2 3 4 5 9。
第三次, 3 和 2 对比,2 比 3 小,所以本次循环结束,也就是上面代码中的内循环结束,进入下一内循环。
不知道这样写能不能让大家更好的理解插入排序,如果有疑问或者不对的地方,可以下方留言交流。