插入排序

本文详细解析了JDK 1.8中Arrays.sort方法使用的普通插入排序与成对插入排序算法。阐述了两种排序的基本原理,展示了源码实现细节,并通过实例分析了成对插入排序的具体过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

插入排序

在jdk1.8源码中,Arrays.sort方法中运用了普通插入排序与成对插入排序,这里主要讲解这两种算法思想

普通插入排序

普通插入排序的思想是,每一步将一个待排序的记录,将其顺序大小插入到前面已经排序的序列的合适位置。从后向前找合适位置

下面是Arrays.sort中的普通插入排序,边界是left到right

for (int i = left, j = i; i < right; j = ++i) {
    int ai = a[i + 1];
    while (ai < a[j]) {
        a[j + 1] = a[j];
        if (j-- == left) {
            break;
        }
    }
    a[j + 1] = ai;
}

可能你一下子看不出来是普通插入排序,因为你可能习惯了以下的形式

for (int i=left+1;i<=right;i++) {
    int temp = a[i];
    int j=i;
    while (j>left&&a[j-1]>temp) {
        a[j]=a[j-1];
        j--;
    }
    a[j]=temp;
}

源码中的插入排序稍微做了一点变换,将j>left判断放置进while内部

成对插入排序

在排序源码中,会发现当设置的left不是边界时,可能会进入成对插入排序

以下为源码的成对插入排序

//优化,跳过升序部分
do {
    if (left >= right) {
        return;
    }
} while (a[++left] >= a[left - 1]);
//成对插入排序
for (int k = left; ++left <= right; k = ++left) {
    int a1 = a[k], a2 = a[left];

    if (a1 < a2) {
        a2 = a1; a1 = a[left];
    }
    while (a1 < a[--k]) {
        a[k + 2] = a[k];
    }
    a[++k + 1] = a1;

    while (a2 < a[--k]) {
        a[k + 1] = a[k];
    }
    a[k + 1] = a2;
}
int last = a[right];

while (last < a[--right]) {
    a[right + 1] = a[right];
}
a[right + 1] = last;

成对插入排序的思想是:

(1)将要插入的数据,第一个值赋值a1,第二个值赋值a2,

(2)然后判断a1与a2的大小,使a1要大于a2

(3)接下来,首先是插入大的数值a1,将a1与k之前的数字一一比较,直到数值小于a1为止,把a1插入到合适的位置,注意:这里的相隔距离为2

(4)接下来,插入小的数值a2,将a2与此时k之前的数字一一比较,直到数值小于a2为止,将a2插入到合适的位置,注意:这里的相隔距离为1

(5)最后把最后一个没有遍历到的数据插入到合适位置
这里的a2与a1的间隔的差别是因为,a1>a2,大于a1的一定大于a2

成对插入排序的例子分析

这里通过一个简单的数组来说明运行的过程

a[4,7,5,3,6,2,1]

通过优化部分后,left=2,指向5的部分,进入成对插入排序for循环

分析第一次进入

for (int k = left; ++left <= right; k = ++left) {		//k=2,left=3
    int a1 = a[k], a2 = a[left];		//a1=5,a2=3
    if (a1 < a2) {
        a2 = a1; a1 = a[left];
    }
    while (a1 < a[--k]) {		//k=1  a[3]=a[1]=7  此时数组是  [4,7,5,7,6,2,1],出循环时k=0
        a[k + 2] = a[k];
    }
    a[++k + 1] = a1;		//k=1 a[2]=a1=5,此时数组是  [4,7,5,7,6,2,1]
    while (a2 < a[--k]) {	//k=0  a[1]=a[0]=4  此时数组是  [4,4,5,7,6,2,1],出循环时k=-1
        a[k + 1] = a[k];
    }
    a[k + 1] = a2;		//a[0]=3,此时数组是[3,4,5,7,6,2,1],发现这一轮有两个数字插入排序好了,一个是5,一个是3
}

后面的每一轮跟此轮类似

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值