算法基础1-插入排序

排序算法可以说是算法中最基础的一部分知识,插入排序又可以称之为是排序算法中的基础,所以理解插入排序的算法原理对于学习算法也是很有帮助的。

算法导论中对于插入算法是这样描述的:插入排序的工作方式像许多人排序一手扑克牌,开始时我们的左手为空并且桌子上的牌面向下(需要排序的数组),然后,我们每次从桌子上拿走一张牌,从右到左将它与已在左手中的每张牌进行比较,最后将它插入左手中正确的位置,所以我们拿在手中的牌总是有序的。

《算法导论》在插入排序这个内容中提到了一个概念:循环不变式。我对于循环不变式的理解是:在插入排序中,循环不变式可以看做为一个遵循排序规则的、在排序过程中不断改变的、属于排序数组的子集。

以数组A={5,2,4,6,1,3}为例,插入排序开始时:循环不变式为{5};完成元素6的排序时:循环不变式为{2,4,5,6};完成排序之后:循环不变式为{1,2,3,4,5,6},即排序的最终结果

以上述A={5,2,4,6,1,3}为例,解释插入排序原理:

初始化状态如下表所示:此时的循环不变式为A[0]

索引012345
524613

 第一次排序:从索引为1的位置,即2视为关键值,开始排序,此时循环不变式为:{5},即A[0],将索引视为i,也可以说是A[0...i-1]。插入排序就是为关键值在循环不变式中从右向左寻找合适的位置,如果循环不变式中有数比关键值大,则该数向右移动一位。

索引012345
254613

第二次排序:从索引为2的位置,即4视为关键值,开始排序,此时循环不变式为:{2,5},即A[0...1],将索引视为i,也可以说是A[0...i-1]。将关键值与循环不变式中的值进行比较。

索引012345
245613

第三次排序:从索引为3的位置,即6视为关键值,开始排序,此时循环不变式为:{2,4,5},即A[0...2],将索引视为i,也可以说是A[0...i-1]。将关键值与循环不变式中的值进行比较。 

索引012345
245613

第四次排序:从索引为4的位置,即1视为关键值,开始排序,此时循环不变式为:{2,4,5,6},即A[0...3],将索引视为i,也可以说是A[0...i-1]。将关键值与循环不变式中的值进行比较。 此时循环不变式中的值都比1要大。

索引012345
124563

第五次排序:从索引为5的位置,即3视为关键值,开始排序,此时循环不变式为:{1,2,4,5,6},即A[0...4],将索引视为i,也可以说是A[0...i-1]。将关键值与循环不变式中的值进行比较。

索引012345
123456

此时排序完成。 

以下是具体的Java代码实现:

/**
 * 插入排序
 */
public class Insert_sort {
    public static void main(String[] args) {
        int[] arr1 = {5, 2, 4, 6, 1, 3};
        // 插入排序
        insertion_sort(arr1);
    }

    public static void insertion_sort(int[] arr1) {
        System.out.println("初始值:");
        for (int i : arr1) {
            System.out.print(i + "  ");
        }
        System.out.println();
        // for循环从1号元素开始,是将0号元素作为了初始循环不变式
        for (int i = 1; i < arr1.length; i++){
            int key = arr1[i];
            
            // i号元素,即关键值与循环不变式中的元素进行
            int j = i -1;
            // 循环不变式中的元素都是已经排好序的
            // 将循环不变式中所有比关键值大的数向右移动一位
            while(j >= 0 && arr1[j] > key){
                arr1[j+1] = arr1[j];
                j -= 1;
            }
            // 移动好之后,循环不变式中空余的位置就是关键值,即原来的i号元素的位置
            arr3[j+1] = key;
        }
        System.out.println("排序后结果:");
        for (int i : arr1) {
            System.out.print(i + "  ");
        }

    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值