JAVA数据结构和算法——简单排序

2018-08-24  本文已影响0人  往昔負流年

冒泡排序

    /**
     * 冒泡排序
     * 需要N*(N-1)/2约等于N*N/2次比较,因为满足条件才交换所以交换的次数少于比较的次数
     * 如果数据是随机的那么大概一半数据需要交换,则交换次数为N*N/4。
     * 交换和比较操作次数都和N*N成正比。常数不算在大O表示法中可以忽悠2和4,
     * 所以冒泡排序运行需要O(N*N)时间级别。
     * 不变性:out右边的数据总是有序的
     * 个人理解:N*N/2次比较+交换次数为N*N/4
     * @param arr
     */
    public void bubbleSort(int[] arr) {
        int length = arr.length;
        for(int out = length-1; out > 0; out--) {
            //下标大于out的数据是已经排好序了的所以没有必要比较交换
            for(int in = 0; in < out; in++) {
                //比较
                if(arr[in] > arr[in+1]) {
                    //如果满足左边大于右边则交换
                    int temp = arr[in];
                    arr[in] = arr[in+1];
                    arr[in+1] = temp;
                }
            }
        }
    }

选择排序

    /**
     * 选择排序
     * 选择排序和冒泡排序执行了相同次数的比较:N*(N-1)/2。
     * N值很大时,比较次数是主要的,所以结论是选择排序和冒泡排序一样运行了O(N*N)时间。
     * 但是选择排序无疑更快,因为他进行交换次数少的多(O(N))。
     * 当N值较小时,特别是如果交换时间级比比较时间级大得多时,选择排序实际上是相当快的。
     * 不变性:out左边的数据总是有序的
     * 个人理解:其实是N*(N-1)/2次比较+(O(N))次交换+N*(N-1)/4复制
     * @param arr
     */
    public void selectionSort(int[] arr) {
        for(int out = 0; out < arr.length - 1; out++) {
            //寻找最小值的下标
            int min = out;
            for(int in = out + 1; in < arr.length; in++) {
                if(arr[in] < arr[min]) {
                   //其实按照个人理解这个需要N*(N-1)/4复制
                    min = in;
                }
            }
            //把最小放在最左边
            int temp = arr[min];
            arr[min] = arr[out];
            arr[out] = temp;
        }
    }

插入排序

    /**
     * 插入排序
     * 不变性:在每趟结束结束时,在讲temp位置的项插入后,比out变量下标小的数据项都是局部有序的。
     * 效率:在第一趟排序中最多比较一次,第二趟最多比较两次,以此类推最后一躺最多比较N-1次。
     * 因此1+2+3+...+N-1 = N*(N-1)/2,然而因为在每一趟排序发现插入点之前,平均只有全体数据项的一半
     * 真的进行了比较,我们除以2得到N*(N-1)/4.
     * 复制次数大致等于比较次数。然后一次复制与一次交换的时间耗费不同,所以相对于随机数据,这个算法比冒泡排序快一倍,
     * 比选择排序略快。于其他简单排序一样对于随机顺序的数据进行插入排序也需要O(N*N)的时间级。
     * 对于已经有序或基本有序的数据来说,插入排序要好得多。
     * 个人理解:N*(N-1)/4比较+N*(N-1)/4次复制+N次复制
     * @param arr
     */
    public void insertionSort(int[] arr) {
        for(int out = 1; out < arr.length; out++) {
            int temp = arr[out];
            int in = out;
            while (in > 0 && arr[in-1] >= temp) {
                 //个人理解这儿是N*(N-1)/4次复制
                arr[in] = arr[in-1];
                --in;
            }
             //个人理解这儿是N次复制
            arr[in] = temp;

        }
    }

排序算法的选择

除非手边没有算法书可参考,一般情况几乎不太用冒泡排序。选择排序虽然把交换次数降到最低,但比较次数依然很大。当数据量很小,并且交换数据相对于比较数据更加耗时的情况下可以用选择排序。在大多数的情况下假设数据量比较小,或者基本有序时,插入排序是三种简单排序中最好的选择。对于更大数据量的排序来说,快速排序通常是更快的方法。
除了在速度方面比较排序算法外,还有一个衡量标准就是算法需要的内存空间多大。这三种算法都除了数组外几乎不需要其他的内存空间。所有排序算法都需要一个额外的变量来暂时存储变换时的数据项。

上一篇下一篇

猜你喜欢

热点阅读