插入排序java版

基本思想:每趟将一个带排序的记录,按其关键字的大小插入到已经排好序的一组记录的适当位置上,知道所有待排序的记录全部重新插入为止。

根据查找方法的不同,分为直接插入排序、折半插入排序和希尔排序。

直接插入排序是最简单的一种,其基本操作是将一条记录插入到已经排序号的有序列表中,从而得到一个新的、记录数增1的有序表。

public class InsertSort {
    
    public static void main(String[] args) {
        int[] array = new int[]{2, 6, 3, 8, 9, 0, 1, 7, 4};
        InsertSort(array);
    }
    
    public static void printArray(int[] array) {
        for(int i : array) {
            System.out.printf("%d\t", i);
        }
        System.out.println();
    }
    
    public static void InsertSort(int[] array) {
        if( array == null) {
            return;
        }
        
        for (int i = 1; i < array.length; i++) {
            if( array[i] < array[i - 1]) {
                int key = array[i];
                int j;
                for ( j = i - 1; j >= 0; j--) {
                    if ( key < array[j]) {
                        array[j + 1] = array[j];
                    } else {
                        break;
                    }
                }
                array[j + 1] = key;
            }
            printArray(array);
        }
    }
}

时间复杂度: O(n2)

空间复杂度:O(1)

算法特点:

  1. 稳定排序
  2. 算法简单,容易实现
  3. 适用于与链式表结构
  4. 更适合初始记录基本有序的情况,当初始记录无序且n较大时,此算法时间复杂度高,不宜采用。

 

 

折半插入排序,用折半查找法来查找当前记录在以排好的序列中的插入位置,由此进行的插入排序称之为折半插入排序

public class BInsertSort {
    public static void main(String[] args) {
        int[] array = new int[]{2, 6, 3, 8, 9, 0, 1, 7, 4};
        BInsertSort(array);
    }
    
    
    public static void BInsertSort(int[] array) {
        printArray(array);
        
        for (int i = 1; i < array.length; i++) {
            int key = array[i];
            int low = 0, high = i - 1;
            while(low <= high) {
                int mod = (low + high) / 2;
                if (key < array[mod]) {
                    high = mod - 1;
                } else {
                    low = mod + 1;
                }
            }
            
            for (int j = i-1; j >= high + 1; j--) {
                array[j+1] = array[j];
            }
            array[high + 1] = key;
            printArray(array);
        }
        
    }
    
    
    public static void printArray(int[] array) {
        for(int i : array) {
            System.out.printf("%d\t", i);
        }
        System.out.println();
    }
}

算法时间复杂度:从时间上比较,折半查找比顺序查找快,所以就平均性能来说,折半插入排序优先于直接插入排序,在平均情况下,折半插入排序仅减少了关键字间的比较次数,而记录的移动次数不变,因此,折半插入排序的事件复杂度任为O(n2)

空间复杂度:折半插入排序所需附加存储空间和直接插入排序相同,只需要一个记录的辅助空间,所以空间复杂度任为O(n2)

算法特点:

  1. 稳定排序
  2. 因为进行折半查找,所以只能用于顺序结构,不能用于链式结构
  3. 适合初始记录无序,n较大时的情况

 希尔排序又称缩小增量排序,是插入排序的一种。直接插入排序,当待排序的记录个数较少而且排序序列基本有序时,效率较高。希尔排序基于这两点,对直接插入排序进行改进。

希尔排序实质是采用分组插入的方法,先将整个待排序的记录序列分割成几组,从而减少参与直接插入排序的数据量,对每组分别进行直接插入排序,然后增加每组的数据量,重新分组。这样经过几次分组排序后,整个序列中的记录“基本有序”时,再对全体记录进行一次插入排序。

希尔对记录的分组,不是简单地“逐段分割”,而是将相隔某个“增量”的记录分为一组。算法步骤如下:

  1. 第一趟取增量d1(d1 < n) 把全部记录分成d1组,所有间隔为d1的记录分在同一组,在各个组中进行直接插入排序。
  2. 第二趟取增量d2(d2 < d1),重复上诉的分组和排序。
  3. 依次类推直到增量等于1,所有记录在同一组中进行直接插入排序为止。
    public static void ShellSort(int[] array, int dk) {
        for(int i = dk; i < array.length; i+= 1) {
            if( array[i] < array[i - dk]) {
                int key = array[i];
                int j;
                for ( j = i - dk; j >= 0; j -= dk) {
                    if ( key < array[j]) {
                        array[j + dk] = array[j];
                    } else {
                        break;
                    }
                }
                array[j + dk] = key;
            }
            printArray(array);
        }
    }
    
    public static void ShellSort(int[] array, int[] dt) {
        printArray(array);
        for(int d : dt) {
            ShellSort(array, d);
        }
    }

 

时间复杂度:O(n3/2)

空间复杂度:O(1)

算法特点:

  1. 记录跳跃式移动导致排序方法是不稳定的。
  2. 只能用于顺序结构,不能用于链式结构。
  3. 增量序列可以有各种取法,但应该是增量序列中的值没有除1之外的公因子,并且最后一个增量值必然等于1.
  4. 记录总的比较次数和移动次数都不比直接插入排序要少,n越大,效果越明显。所以适合初始记录无序,n较大时的情况。
posted @ 2020-09-15 09:24  悦尔  阅读(220)  评论(0编辑  收藏  举报