我的笔记之插入排序

插入排序

  • 插入排序包括直接插入、折半插入、希尔排序;
  • 任何一种插入排序的每趟排序都不会产生全局有序区;

排序算法的稳定性:是指如果待排序的表中存在多个关键字相同的元素,经过排序后这些元素之间的相对次序保持不变,则这种排序方法是稳定的;反之是不稳定的;

直接插入

  • 时间复杂度 O(n^2) 属于稳定的排序;
  • 取无序区开头元素a[ j ]插到有序区的适当位置;
  • 在有序区从后往前找,凡是大于a[ j ]的均后移一个位置,直到找到一个最大的小于等于a[ j ]的元素位置,将a[ j ]插入到它后面;

private static void directInsertSort1(int[] a) {
    //从第二个元素开始,将元素插入到已排好的数组中
    for (int i = 1; i < a.length; i++) {
        int key = a[i];//要插入的值
        int j = i - 1;//从已排好序的数组的最后一个元素向左开始比较
        while (a[j] > key && j >= 0) {//找到最大的小于等于key的值的位置j,并将大于key的值后移
            a[j + 1] = a[j];
            j--;
        }
        //此时的j代表着插入位置的左边位置下标,即有序区中最大的小于等于key的值的位置;
        a[j + 1] = key;
    }
}复制代码

以下为参考链接,大佬在文章里面有直接插入排序的动图演示,建议看一下

折半插入

  • 时间复杂度 O(n^2) 属于稳定的排序;
  • 用折半查找方法先在有序区找到插入位置,再通过移动元素进行插入;

private static void binaryInsertSort(int arr[]) {
     int i, j, half, low,high,key;
     int length=arr.length;
     for (i = 1; i < length; i++) {//从第二个元素开始遍历
         low = 0;
         high = i - 1;//有序区的最后一个元素下标
         key = arr[i];//要插入的元素
         //折半查找插入位置
         while (low <= high) {//跳出循环时low-high==1
             half = (low + high) / 2;
             if (arr[half] > key) {
                 high = half - 1;
             } else {
                 low = half + 1;
             }
         }
        /*此时,因为最终导致low>high的原因是:
         在两者相遇之后low在half的基础上增加1或者high在half的基础上减少1,
         所以low-high==1;
         倒回循环中:
         对high的最后一次操作后,half在high右边,且arr[half]>key,故arr[high+1]>key;
         对low的最后一次操作后,half在low的左边,且arr[half]<=key,故arr[low-1]<=key;
         又因为low=high+1,所以a[low]>key且a[high]<=key
         所以low即为插入位置*/
         for (j = i - 1; j >= low; j--) {//移动插入位置之后的元素
             arr[j + 1] = arr[j];
             }
         //插入元素
         arr[low] = key;
     }
 }复制代码

希尔排序

  • 时间复杂度 O(n) 属于不稳定的排序;
  • 通过某个增量gap,每隔gap取一个数组元素分到一个组,然后在组内进行插入排序,随后逐步缩小增量,继续按组进行插入排序操作;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。


//希尔排序 针对有序序列在插入时采用交换法
private static void sort(int[] arr) {
    //1.逐步缩小增量gap
    for (int gap = arr.length / 2; gap > 0; gap /= 2) {
        //2.从第gap个元素,逐个对其所在组进行直接插入排序操作
        for (int i = gap; i < arr.length; i++) {
            int j = i;
            //3.交换,插入排序采用交换法
            while (j - gap >= 0 && arr[j] < arr[j - gap]) {
                swap(arr, j, j - gap);
                j -= gap;
            }
        }
    }
}
//交换数组元素,注意这个交换函数没有用临时变量!!!
private static void swap(int[] arr, int a, int b) {
    arr[a] = arr[a] + arr[b];
    arr[b] = arr[a] - arr[b];
    arr[a] = arr[a] - arr[b];
}复制代码

以下为参考文章,大佬讲的也比较详细,而且还列举了希尔排序的另一种实现方法,建议看一下:

参考:www.cnblogs.com/chengxiao/p…



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值