zoukankan      html  css  js  c++  java
  • 排序算法(三) 插入排序

    InsertionSort

    1.动图演示

    1. 动图1

    双层循环,外部循环选择需要与数组中前面元素比较的元素。内层循环,从该选定元素开始 与 该元素左边的元素进行比较。
    如果选定元素小于左边元素 则与之交换位置。直至找到正确的位置,此次内层循环后,左侧部分元素已经有序。

    2.动图2

    动图1的优化版本。每次比较的时候不再与前面的元素交换位置。如果选定元素 比 左边的小,则让左边元素覆盖相邻右边元素。这样减少了许多交换次数,提高了效率。

    2.代码实现

    //测试工具类在这里 https://www.cnblogs.com/paidaxing7090/p/15080493.html
    import 测试工具类.SortTestHelper;
    
    public class InsertionSort2{
    
        // 我们的算法类不允许产生任何实例
        private InsertionSort2(){}
    
        public static void sort(Comparable[] arr){
    
            int n = arr.length;
            for (int i = 0; i < n; i++) {
    
                // 寻找元素arr[i]合适的插入位置
    
                // 写法1
    //            for( int j = i ; j > 0 ; j -- )
    //                if( arr[j].compareTo( arr[j-1] ) < 0 )
    //                    swap( arr, j , j-1 );
    //                else
    //                    break;
    
                //写法2比较精简与写法1 没差别 ,对应动图1
    //            for( int j = i; j > 0 && arr[j].compareTo(arr[j-1]) < 0 ; j--)
    //                swap(arr, j, j-1);
    
                //  写法3 对应动图2
                Comparable e = arr[i];
                int j = i;
                for( ; j > 0 && arr[j-1].compareTo(e) > 0 ; j--)
                    arr[j] = arr[j-1];
                arr[j] = e;
    
            }
        }
        public static void sort(Comparable[] arr,int l,int r){
        	  
               for (int i = l; i <=r; i++) {
    
                   // 寻找元素arr[i]合适的插入位置
    
                   // 写法1 交换元素
    //               for( int j = i ; j > 0 ; j -- )
    //                   if( arr[j].compareTo( arr[j-1] ) < 0 )
    //                       swap( arr, j , j-1 );
    //                   else
    //                       break;
    
                   // 写法2比较精简与写法1 没差别 ,对应动图1
    //               for( int j = i; j > 0 && arr[j].compareTo(arr[j-1]) < 0 ; j--)
    //                   swap(arr, j, j-1);
    
                   // 写法3 对应动图2
                   Comparable e = arr[i];
                   int j = i;
                   for( ; j > l && arr[j-1].compareTo(e) > 0 ; j--)
                       arr[j] = arr[j-1];
                   arr[j] = e;
    
               }
        }
    
        private static void swap(Object[] arr, int i, int j) {
            Object t = arr[i];
            arr[i] = arr[j];
            arr[j] = t;
        }
    
        // 测试InsertionSort
        public static void main(String[] args) {
            int N0 = 20000;
            Integer[] arr0 = SortTestHelper.generateRandomArray(N0, 0, 100000);
            Integer[] arr = arr0.clone();
            SortTestHelper.testSort("sort.InsertionSort", arr0);
            SortTestHelper.testSort("sort.InsertionSort2", arr);
            int N2 = 40000;
            Integer[] arr2 = SortTestHelper.generateRandomArray(N2, 0, 100000);
            SortTestHelper.testSort("sort.InsertionSort2", arr2);
            return;
        }
    }
    
    

    3.测试结果

    对于同样的数组,可以看到优化后的插入排序效率提升了。同时,优化后的时间复杂度还是在O(n^2)级别。

    4.算法分析

    4.1描述

    插入排序(InsertionSort),一般也被称为直接插入排序。对于少量元素的排序,它是一个有效的算法。插入排序是一种最简单的排序方法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增 1 的有序表。在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动。

    4.2分析


    插入排序的基本思路简单,平均时间复杂度为O(n^2)。但是如果所排序数组是近乎有序的,则它的时间复杂度为O(n),这是高级排序算法也达不到的时间复杂度。显然,对于近乎有序的数组,大部分情况下都不需要移动元素。
    当数组中存在相等元素时,插入排序中不会有操作 改变相等元素的相对位置,所以插入排序是稳定的。

  • 相关阅读:
    BZOJ2253: [2010 Beijing wc]纸箱堆叠
    解题:CF1055F Tree and XOR
    解题:JSOI 2011 柠檬
    解题:NOI 2009 诗人小G
    2019.2.28&2019.3.1 考试
    省选前作业题汇总2
    解题:LNOI 2014 LCA
    省选前作业题汇总1
    2019.2.26 考试
    解题:SDOI 2014 重建
  • 原文地址:https://www.cnblogs.com/paidaxing7090/p/15088809.html
Copyright © 2011-2022 走看看