闲话插入排序小优化

闲来没事做,随便翻了翻手边那本N年未动的书,感觉一个关于插入排序的例子不错,贴贴吧。。。。

插入排序,概念就不说了,想象一下斗地主时怎么排列手牌。

循环从右至左,进行筛选,跟踪被筛选的元素。只要 该元素具有前驱(下标>0)&& 没有到达最终位置(改元素小于它的前驱),就交换改元素和它的前驱。

示例1

    public int insertSort1(int[] arr) {
        
        long start = System.nanoTime();
        for (int i = 1; i < arr.length; i++) {
            for (int j = i; j > 0 && arr[j - 1] > arr[j]; j--) {
                swap(arr, j - 1, j);// 交换两个元素
            }
        }
        long end = System.nanoTime();
        
        return (int) (end - start);// return cost
    }

一般这么写,看着有点不舒服,感觉那个函数似乎可以优化一下,函数调用时压栈、出栈、保存现场、恢复现场,这些操作倒腾得慌,那就把函数体直接替换到内层循环里吧,很多编译器会完成这种优化,不知道我们大Java如何,有路过的,了解的给科普点,谢谢。

示例2

    public int insertSort2(int[] arr) {
        int tmp = 0;
        
        long start = System.nanoTime();
        for (int i = 1; i < arr.length; i++) {
            for (int j = i; j > 0 && arr[j - 1] > arr[j]; j--) {
                // swap函数体内容
                tmp = arr[j - 1];
                arr[j - 1] = arr[j];
                arr[j] = tmp;
            }
        }
        long end = System.nanoTime();
        
        return (int) (end - start);
    }

进一步细看,发现内层循环中总是给变量tmp赋同样的值arr[i]的初始值,所以可以把关于tmp变量的操作移出内层循环,然后是这样的:

示例3

    public int insertSort3(int[] arr) {
        int tmp = 0;
        int j = 0;
        
        long start = System.nanoTime();
        for (int i = 1; i < arr.length; i++) {
            tmp = arr[i];
            j = i;
            for (; j > 0 && arr[j - 1] > tmp; j--) {
                arr[j] = arr[j - 1];
            }
            arr[j] = tmp;
        }
        long end = System.nanoTime();
        
        return (int) (end - start);
    }

只要tmp小于已排序部分的元素值,就右移一个位置,最终移到正确的位置上。

随便测试了几组数据,结果上课,第二种最快。感觉上应该是第三种方式最快的,小疑惑。。。。。

test array size is 1214


1 2 3 4
insertSort1 21263 ns 21522 ns 20612 ns 21303 ns
insertSort2 18064 ns 17099 ns 17946 ns 16844 ns
insertSort3 19716 ns 20687 ns 19515 ns 19280 ns



你可能感兴趣的:(闲话插入排序小优化)