【问题标题】:Why is Insertion Sort faster than Bubble Sort and Heap Sort in practice?为什么在实践中插入排序比冒泡排序和堆排序快?
【发布时间】:2014-12-11 23:39:03
【问题描述】:

我在链接中看到(http://bigocheatsheet.com/)插入排序的复杂性与冒泡排序相同,而且堆排序也比这两者都好。但是当我创建一个示例程序并比较插入排序所花费的时间时,这是令人难以置信的。

Class 用于测试排序算法。

public class TestSorts {

    public static void main(String[] args) {
        System.out.println("starting");
        Calendar startInstance = null;
        Calendar endInstance = null;

        //Getting the array to sort
        startInstance= Calendar.getInstance();
        //int[] arrayToSort = ArrayClass.getArray(1000);
        int[] arrayToSort = ArrayClass.getWorstArray(10000000);
        endInstance= Calendar.getInstance();
        long timeTakenToGetArray = endInstance.getTimeInMillis()- startInstance.getTimeInMillis();
        System.out.println("StartTime : "+startInstance.getTimeInMillis());
        System.out.println("EndTime : "+endInstance.getTimeInMillis());
        System.out.println("TimeTakenToGetArray : "+timeTakenToGetArray);

        //Bubble Sort       
        startInstance= Calendar.getInstance();
        int[] bubbleSorted = BubbleSort.sort(arrayToSort);
        endInstance= Calendar.getInstance();
        long timeTakenBubble = endInstance.getTimeInMillis() - startInstance.getTimeInMillis();
        System.out.println("StartTime : "+startInstance.getTimeInMillis());
        System.out.println("EndTime : "+endInstance.getTimeInMillis());
        System.out.println("Bubble : "+timeTakenBubble);

        //InsertionSort
        startInstance= Calendar.getInstance();
        int[] insertionSorted = InsertionSort.sort(arrayToSort);
        endInstance= Calendar.getInstance();
        long timeTakenInsertion = endInstance.getTimeInMillis() - startInstance.getTimeInMillis();
        System.out.println("StartTime : "+startInstance.getTimeInMillis());
        System.out.println("EndTime : "+endInstance.getTimeInMillis());
        System.out.println("Insertion : "+timeTakenInsertion);

        //HeapSort
        startInstance= Calendar.getInstance();
        int[] heapSorted = HeapSort.sort(arrayToSort);
        endInstance= Calendar.getInstance();
        long timeTakenHeap = endInstance.getTimeInMillis() - startInstance.getTimeInMillis();
        System.out.println("StartTime : "+startInstance.getTimeInMillis());
        System.out.println("EndTime : "+endInstance.getTimeInMillis());
        System.out.println("Heap : "+timeTakenHeap);

        startInstance= Calendar.getInstance();
        arraysAreEqual(bubbleSorted, insertionSorted, heapSorted);
        endInstance= Calendar.getInstance();
        long timeTakenToCompare = endInstance.getTimeInMillis() - startInstance.getTimeInMillis();
        System.out.println("StartTime : "+startInstance.getTimeInMillis());
        System.out.println("EndTime : "+endInstance.getTimeInMillis());
        System.out.println("TimeTakenToCompare : "+timeTakenToCompare);

    }



    //Method to compare whether the sorted arrays are equal
    static void arraysAreEqual(int[] bubbleSorted,int[] insertionSorted,int[] heapSorted)
    {
        for(int i =0;i<bubbleSorted.length;i++)
        {
            if((bubbleSorted[i]!=insertionSorted[i])||(heapSorted[i]!=insertionSorted[i])||(heapSorted[i]!=bubbleSorted[i]))
            {
                System.out.println("Bubble : "+bubbleSorted[i]);
                System.out.println("Insertion : "+insertionSorted[i]);
                System.out.println("Heap : "+heapSorted[i]);
            }
        }
    }


}

冒泡排序类

public class BubbleSort {

    static int[] sort(int[] arrayToSort)
    {
        int length = arrayToSort.length;
        for(int i = 0;i<length;i++)
        {
            for(int j = i+1;j<length;j++)
            {
                if(arrayToSort[i]>arrayToSort[j])
                {
                    arrayToSort[i]+=arrayToSort[j];
                    arrayToSort[j] = arrayToSort[i] - arrayToSort[j];
                    arrayToSort[i] = arrayToSort[i] - arrayToSort[j];
                }
            }
        }

        return arrayToSort;
    }

}

插入排序的类

public class InsertionSort {

    static int[] sort(int[] arrayToSort)
    {
         for (int i = 0; i < arrayToSort.length; i++) {  
               int value = arrayToSort[i];  
               int j = i - 1;  
               while (j >= 0 && arrayToSort[j] > value) {  
                   arrayToSort[j + 1] = arrayToSort[j];  
                j = j - 1;  
               }  
               arrayToSort[j + 1] = value;  

              }  
         return arrayToSort;
    }

}

堆排序的类

public class HeapSort {

    static int a[];
    static int[] sort(int[] arrayToSort)
    {
        a = arrayToSort;

        heapsort();
        return a;
    }
    static void heapsort()
    {

        int size = a.length; 
        maxHeapify(size);
        for(int i =a.length-1;i>=1;i--)
        {
            swap(0,i);
            size--;
            maxHeapify(size);
        }
    }
    static void maxHeapify(int size)
    {
        for(int i =size/2-1;i>=0;i--)
        {
            heapify(i,size);
        }
    }


    static void heapify(int i,int size)
    {
        int left = 2*i+1;
        int right = 2*i+2;
        int max = i;
        if(left<size&&a[left]>a[i])
        {
            max = left;
        }
        if(right<size&&a[right]>a[max])
        {
            max = right;
        }
        if(max!=i)
        {
            swap(i,max);
            heapify(max,size);
        }

    }
    static void swap(int i,int j)
    {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }

}

创建数组的类

import java.util.Random;


public class ArrayClass {

    public static int[] getArray(int size)
    {
        int array[] = new int[size];

        for(int i =0;i<size;i++)
        {
            int s = randomInt(10,size);

            array[i] = s;

        }

        return array;
    }

    private static int randomInt(int min,int max)
    {
        Random rn = new Random();

        int randomNumber = rn.nextInt((max - min) + 1) + min;

        return randomNumber;
    }

    public static int[] getBestArray(int size)
    {
        int array[] = new int[size];
        for(int i =0;i<size;i++)
        {
            array[i]=i+1;
        }
        return array;

    }
    public static int[] getWorstArray(int size)
    {
        int array[] = new int[size];
        for(int i =size-1;i>0;i--)
        {
            array[i]=i;
        }
        return array;

    }

}

我尝试了所有情况,例如最佳情况、最坏情况和平均情况。但在所有情况下,插入排序都比冒泡排序和堆排序快得多。在最坏的情况下,理论上堆排序应该是最好的。

当我使用 100000 作为最坏情况的输入时,请找到以下测试结果。

starting
StartTime : 1413470225347
EndTime : 1413470225362
TimeTakenToGetArray : 15
StartTime : 1413470225362
EndTime : 1413470226894
Bubble : 1532
StartTime : 1413470226894
EndTime : 1413470226896
Insertion : 2
StartTime : 1413470226896
EndTime : 1413470233474
Heap : 6578
StartTime : 1413470233474
EndTime : 1413470233488
TimeTakenToCompare : 14

您能否告诉我为什么插入排序比堆排序提供更快的输出?

【问题讨论】:

  • 此外,JIT 编译器完全有可能使用您的基准测试工具来破坏您的基准测试。
  • getWorstArray 应该做什么?反向填写不会改变任何内容。

标签: java algorithm sorting


【解决方案1】:

对于小列表,插入排序比其他排序更快,因为它们在第一次迭代(循环)中将每个项目放置在正确的位置。减慢它的速度是将所有东西都移出插入的方式。这就是列表必须很小的原因。

【讨论】:

    【解决方案2】:

    您的排序方法实际上是对原始数组进行排序,对于已排序的列表,InsertionSort 是 O(n)。由于您首先执行 BubbleSort,因此您给了 InsertionSort 一个不公平的优势。

    为了更公平的比较,您应该制作原始数组的相同副本(在计时之外),并为每个排序例程提供一个单独的副本。这样您就可以在相同的输入下进行直接比较。

    【讨论】:

      【解决方案3】:

      有几个错误:

      • 您的 BubbleSort 对数组进行排序(就地!),然后您将相同的数组传递给下一个方法 (InsertionSort)。

      • getWorstArray 正在返回一个排序数组。在另一个方向运行循环不会改变元素的顺序。而且无论如何,您使用的是极端情况(已排序,反向排序,没关系),您的结果将有偏差。

      • 良好的BubbleSort 提前终止(如果在扫描期间未进行任何交换,则对其进行排序)。

      在这一点上,我会质疑其余的代码。错误通常成群出现(糟糕的一天,没有经验的程序员,...)。检查更多错误。进行单元测试。

      【讨论】:

      • BubbleSort 对于已排序的数组来说是 O(n)。
      • @HunterMcMillen 当 BubbleSort 看到数组时,它没有排序。它按 InsertionSort 到达它的时间排序。因此,BubbleSort 在时间上没有任何优势,而 InsertionSort 则从中获益。
      • 修改了所有的cmets。
      • @Karoly Horvath 感谢您纠正这些问题。现在我得到了我预期的结果。这些问题是由于我的经验。抱歉给您添麻烦了:(
      猜你喜欢
      • 2011-11-30
      • 2018-03-28
      • 2017-03-18
      • 2014-12-04
      • 1970-01-01
      • 2012-05-12
      • 1970-01-01
      • 2019-02-26
      • 2021-05-13
      相关资源
      最近更新 更多