八大排序算法(2)

五、直接插入排序(平均时间复杂度:O(n^2))

        1、介绍:直接插入排序属于内部排序法,是对欲排序的元素以插入的方式找寻该元素的适当位置,以达到排序的目的。

        2、思想:把n个待排序列看成一个有序表和一个无序表,开始时有序表只含有一个元素(通常为第一个元素),无序表中含有第n-1个元素。在排序过程中,每次从无序表抽取一个元素,把它与有序表中的元素依次比较,将它插入有序表中的适当位置,使之成为有序表。

        3、思路图:

        八大排序算法(2)_第1张图片

         4、代码如下:

        

public static void insertSort(int[] arr){
        int insertVal = 0;
        int insertIndex = 0;
        for(int i = 1; i < arr.length; i++) {
            //定义待插入的数
            insertVal = arr[i];
            insertIndex = i - 1; // 即arr[1]的前面这个数的下标

            // 给insertVal 找到插入的位置
            // 说明
            // 1. insertIndex >= 0 保证在给insertVal 找插入位置,不越界
            // 2. insertVal < arr[insertIndex] 待插入的数,还没有找到插入位置
            // 3. 就需要将 arr[insertIndex] 后移
            while (insertIndex >= 0 && insertVal < arr[insertIndex]) {
                arr[insertIndex + 1] = arr[insertIndex];// arr[insertIndex]
                insertIndex--;
            }
            // 当退出while循环时,说明插入的位置找到, insertIndex + 1
            // 举例:理解不了,我们一会 debug
            //这里我们判断是否需要赋值
            if(insertIndex + 1 != i) {
                arr[insertIndex + 1] = insertVal;
            }
        }
    }

        解释:当退出while循环后,说明已经给待插入的元素找到了插入位置,那为什么还要一个if语句判断呢?因为如果insertIndex + 1 = i,说明待插入的元素已经大于有序序列最大元素 ,此时不用再插入了。

六、希尔排序(平均时间复杂度:O(nlogn))

        1、介绍:它是简单插入排序经过改进之后的一个更高效的版本,也称缩小增量排序。因为在简单插入排序算法中,当需要插入的数是较小的数时,有序表中后移的次数明显增多,对效率有些影响。

        2、基本思想:希尔排序是按照一定增量对下标进行分组,对每组使用直接插入排序算法排序;通过对增量的缩小,每组包含的有序元素越来越多,当增量缩减至1时,整个序列被分为一组,算法完成。

        3、思路图:

八大排序算法(2)_第2张图片

八大排序算法(2)_第3张图片 

         4、代码如下:

        ①在对有序序列插入时,使用交换法(使用交换法代价高)

        

public static void shellSort1(int[] arr){
        int temp = 0;
        int gap = arr.length / 2;
        while (gap >= 1){
            for(int i = gap ; i < arr.length; i++){
                for(int j = i - gap; j >= 0; j -= gap){
                    if(arr[j] > arr[j + gap]){
                        temp = arr[j];
                        arr[j] = arr[j + gap];
                        arr[j + gap] = temp;
                    }
                }
            }
            gap /= 2;
        }
    }

        ②在对有序序列插入时,使用位移法

public static void shellSort2(int[] arr){
        //增量gap,并逐渐的缩小增量
        for(int gap = arr.length / 2; gap > 0; gap /= 2){
            for(int i = gap; i < arr.length; i++){
                int j = i;
                int temp = arr[j];
                while (j - gap >= 0 && temp < arr[j - gap]){
                    arr[j] = arr[j - gap];
                    j -= gap;
                }
                arr[j] = temp;
            }
        }
    }

七、简单选择排序(平均时间复杂度:O(n^2))

        1、介绍:选择排序属于内部排序,是从待排序列中,按照指定的规则选出某一元素,再按照规定交换位置后达到排序的目的。

        2、思想:第一次从arr【0】~arr【n-1】中选取最小值与arr【0】交换,第二次从arr【1】~arr【n-1】中选取最小值和arr【1】交换,第n-1次从arr【n-2】~arr【n-1】中选取最小值与arr【n-2】交换,总共进行n-1次,得到一个从小到大的有序序列。

        3、思路:

八大排序算法(2)_第4张图片

        4、代码如下:

         

private static void selectSort(int[] arr){
        //算法先简单再复杂
        for(int i = 0; i < arr.length - 1; i++){
            int min = arr[i];
            int minIndex = i;
            for(int j = i + 1; j < arr.length; j++){
                if(arr[j] < min){
                    min = arr[j];
                    minIndex = j;
                }
            }
            if(minIndex != i){
                arr[minIndex] = arr[i];
                arr[i] = min;
            }
        }
    }

        解释:最后的if语句也是起到一个优化的效果。

你可能感兴趣的:(算法)