话不多说,直接上代码:
package com.example.demo.study;
import org.junit.Test;
public class InsertSort{
/**
* 测试排序
*/
@Test
public void testSort()
{
int[] a = {2, 89, 6, 8, 52, 1, 9, 0};
// int[] b = sort(a);
int[] b = insertSort(a);
System.out.println("开始打印数组a:");
print(b);
}
/**
* 插入排序算法
* @param a
* @return
*/
public int[] sort(int[] a)
{
int[] tmp = null; // 初始数组
int[] tmp1 = {a[0]};
int b = 0;
for (int i = 1; i < a.length; i ++)
{
b = a[i];
// 把tmp1赋值到tmp
tmp = new int[tmp1.length];
tmp = copyArray(tmp, tmp1);
// 对tmp1 扩容
tmp1 = new int[tmp1.length + 1];
tmp1 = copyArray(tmp1, tmp);
for (int j = tmp.length - 1; j >= 0; j --)
{
if (b >= tmp1[j]) // 当前插入值大于当前数组值,直接把当前值查到最后
{
tmp1[j + 1] = b;
break;
}
else // 当前待排序值小于这个值,则把当前元素后移,待排序元素存在当前位置
{
tmp1[j + 1] = tmp1[j];
tmp1[j] = b;
}
}
}
return tmp1;
}
/**
* 把tmp1复制到tmp,并对tmp1扩容
* @param tmp
* @param tmp1
* @return
*/
private int[] copyArray(int[] tmp, int[] tmp1) {
for (int i = 0; i < tmp1.length; i ++)
{
tmp[i] = tmp1[i];
}
return tmp;
}
/**
* 打印数组
* @param a
*/
private void print(int[] a)
{
for (int v : a)
{
System.out.print(v + " ");
}
}
public int[] insertSort(int[] a)
{
int t;
for (int i = 1; i < a.length; i ++)
{
t = a[i]; // 将当前待插入的值暂时存放在t中
int j = i -1;
while (j >= 0)
{
// 待插入值轮流和已排序好的序列比较,如果大于对方,则终止循环,这个位置就是待插入值应该存放的位置
if (t >= a[j])
{
break;
}
else // 如果小于当前值,则将当前值向后跳一位
{
a[j + 1] = a[j];
}
j --;
}
a[j + 1] = t;
}
return a;
}
}
这里我写了2种方法:
方法一、sort(int[] a),这种是最笨的方法,看了教材上的实例就开始写,需要多次复制数组,效率低下,时间复杂度较高,小数组看不出来,大数据就爆炸了。
方法二、官方的写法,在原先基础上去掉了复制数组的过程。
算法思想:
把待排序的数组a看成2个小数组组成的,最开始的左边的小数组只有一个元素a[0],其他的组成另外一个小数组,每次从右边的小数组拿出一个元素,跟左边的元素从右向左依次比较找到插入位置,依次类推,左边(有序)的小数组依次壮大,右边(无序)的数组依次缩小,直至排序完毕,算法结束。
时间复杂度:
最好情况:待排序是个有序数组,每个元素排序过程中只要比较一次,那么比较次数为n次;
最差情况:待排序数组与要排序方向相反(如:升序数组要降序排),那么相当每个后面抽出的元素都要遍历前面的排好序的所有序列,需要比较次数为(1+n)n/2;
总体来说时间复杂度为O(n^2)。
欢迎广大网友指正交流。