zoukankan      html  css  js  c++  java
  • 插入排序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	", 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	", 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较大时的情况。
  • 相关阅读:
    HDU 3951 (博弈) Coin Game
    HDU 3863 (博弈) No Gambling
    HDU 3544 (不平等博弈) Alice's Game
    POJ 3225 (线段树 区间更新) Help with Intervals
    POJ 2528 (线段树 离散化) Mayor's posters
    POJ 3468 (线段树 区间增减) A Simple Problem with Integers
    HDU 1698 (线段树 区间更新) Just a Hook
    POJ (线段树) Who Gets the Most Candies?
    POJ 2828 (线段树 单点更新) Buy Tickets
    HDU 2795 (线段树 单点更新) Billboard
  • 原文地址:https://www.cnblogs.com/maosonglin/p/13671320.html
Copyright © 2011-2022 走看看