插入排序的优化
插入排序是基础的排序方法之一,针对插入排序的优化,网上常见的就两种:
- 查找插入位置时,使用二分法查找
- 衍生出的希尔排序
经代码测试,二分法优化的插入排序感觉并不理想,从时间复杂度上来看,与普通插入排序也相差无几;
对普通的插入排序稍加改造,性能就已经超越二分法优化的情形了。
如下是普通的插入排序代码:
public static void sort(int[] source) {
StopWatch watch = new StopWatch();
watch.start();
// 外层循环:从第二个数开始取值往前插入
for (int i = 1, len = source.length; i < len; i++) {
int targetNum = source[i];
// 内层循环:将当前数与前面排好序的数列进行比较
int j;
for (j = i - 1; j >= 0; j--) {
if (source[j] > targetNum) {
// 当插入的数比前面的一个数小,则往前移动
source[j+1] = source[j];
}
}
source[j+1] = targetNum;
}
watch.stop();
log.info("插入排序耗时: {}", watch.getTotalTimeMillis());
}
经过二分法查找优化的插入排序:
public static void sortWithBinary(int[] source) {
StopWatch watch = new StopWatch();
watch.start();
// 外层循环:从第二个数开始取值往前插入
for (int i = 1, len = source.length; i < len; i++) {
int targetNum = source[i];
int left = 0;
int right = i - 1;
// 经过二分查找之后,最终left坐标即为当前数要插入的位置
while (left <= right) {
int middle = (left + right) / 2;
if (source[middle] <= targetNum) {
left = middle + 1;
} else {
right = middle - 1;
}
}
// 将left坐标之后的数都右移一位
for (int j = i - 1; j >= left; j--) {
source[j+1] = source[j];
}
source[left] = targetNum;
}
watch.stop();
log.info("二分法优化耗时: {}", watch.getTotalTimeMillis());
}
耗时对比:
public static void main(String[] args) {
int[] source = new int[20000];
for (int i = 0; i < 20000; i++) {
source[i] = RandomUtil.randomInt(20000);
}
int[] clone = ArrayUtil.clone(source);
sort(source);
sortWithBinary(clone);
}
algorithms.sort.InsertionSort - 插入排序耗时: 233
algorithms.sort.InsertionSort - 二分法优化耗时: 94
以2w个数字排序测试,二分法优化确实比原始插入排序快不少;
对原始插入排序进行如下优化:
public static void sort(int[] source) {
StopWatch watch = new StopWatch();
watch.start();
// 外层循环:从第二个数开始取值往前插入
for (int i = 1, len = source.length; i < len; i++) {
int targetNum = source[i];
// 内层循环:将当前数与前面排好序的数列进行比较
int j;
for (j = i - 1; j >= 0; j--) {
if (source[j] > targetNum) {
// 当插入的数比前面的一个数小,则往前移动
source[j+1] = source[j];
} else {
// 对比原始插入排序, 增加此else分支
// 如果前面一位数已经比当前插入的数小了,则不用继续往前面循环比较了
break;
}
}
source[j+1] = targetNum;
}
watch.stop();
log.info("插入排序耗时: {}", watch.getTotalTimeMillis());
}
耗时比较:
algorithms.sort.InsertionSort - 插入排序耗时: 56
algorithms.sort.InsertionSort - 二分法优化耗时: 104
若有错误,望指出交流。

浙公网安备 33010602011771号