CSDN话题挑战赛第2期 参赛话题:学习笔记

目录

前言

一、希尔排序

二、快速排序

三、归并排序

总结


前言

在Java学习之初,我们了解了几种常见的排序方法,如:冒泡排序法、选择排序法、插入排序法......但是这些排序法真的高效吗?我们看一看他们处理庞大数组的排序的时候,他们分别的运行时间是多少。在这里,我们生成了一个长度为10w的数组,分别用了这三种排序法进行测试,此时发现他们三种运行时间如下:

java 性能 排序 java效率最高的排序算法_算法

可以看到,这里使用冒泡排序法花了14000毫秒,选择排序法用了3300毫秒,插入排序法用了650毫秒。在这里,插入排序法已经显现出了较大的优势,但是还有没有比插入排序更高效的排序方法呢?当然有

一、希尔排序

希尔排序本质上是对插入排序的优化。我们来看这么一个例子:

java 性能 排序 java效率最高的排序算法_开发语言_02

在这里,前面的数字都已经排好序了,但是最后有一个1,我们都知道,把1插入到2前方就可以解决了。但是计算机会一眼看出来吗?当然不会。我们知道插入排序是从左到右开始判断,那这样最后的1要运算到最后了才可以进行插入,这样就消耗了很多不必要的时间。

我们怎么进行优化呢?

在排序之初,我们可以将较小的数尽量地提到数组的左边,这样就可以减少很多运算。在这里我们使用分组的方法,逐步对数组中较小的数字逐步插入,把较小的数字先移到前边,再进行排序,这样就可以减少很多运算时间了。

java 性能 排序 java效率最高的排序算法_排序算法_03

在这里,我们使用了长度为8的数组,我们首先令数组分为length/2 (4)组,将第0个和第4个看作一组,第1个和第5个看作一组,利用插入排序将这些分组的数字进行排序。同理,排序完成之后,我们又令整个数组分为length/2²(2)组,利用插入排序讲分组之后的数字进行排序。这样我们就将小数字都尽量的移到了整个数组的前边,最后我们再整体利用插入排序,就可以成功地进行排序了。完整代码:

public static void ShellSort(int a[]) {
        for (int i = a.length/2; i > 0; i/=2) {
            for (int j = i; j < a.length; j++) {
                int temp = a[j];
                int index = j - i;
                while (index >= 0 && temp < a[index]) {
                    a[index+i] = a[index];
                    index -= i;
                }
                a[index+i] = temp;
            }
        }
    }

 二、快速排序

快速排序主要利用了递归,主要是先选一个中间值,选择之后将数组中比中间值小的放在中间值的左边,大的放在中间值的右边。完成之后,进行递归,将数组又重新分为两部分,重复操作,直至排序完成

java 性能 排序 java效率最高的排序算法_java 性能 排序_04

 

public static void quickSort(int a[] , int left , int right) {
        int l = left;
        int r = right;
        int mid = (left+right)/2;
        int midValue = a[mid];
        while (l<r) {
            while (a[l] < midValue) {
                l++;
            }
            while (a[r] > midValue) {
                r--;
            }

            if (l>=r) {
                break;
            }
            int n;
            n = a[r];
            a[r] = a[l];
            a[l] = n;

            if (a[r] == midValue) {
                r--;
            }
            if (a[l] == midValue) {
                l++;
            }
        }

        if (l == r) {
            l++;
            r--;
        }

        if (left < l) {
            quickSort(a , left , r);
        }
        if (right > r) {
            quickSort(a , l , right);
        }

    }

三、归并排序

归并排序的主要思想是将数组进行分组,分到最后之后最后合并在一起,利用一个中间数组做中转,最后就可以达到效果了。

java 性能 排序 java效率最高的排序算法_开发语言_05

public static void mergeSort(int[] arr, int left, int right, int[] temp) {
        if(left < right) {
            int mid = (left + right) / 2; //中间索引
            //向左递归进行分解
            mergeSort(arr, left, mid, temp);
            //向右递归进行分解
            mergeSort(arr, mid + 1, right, temp);
            //合并
            merge(arr, left, mid, right, temp);

        }
    }

    public static void merge(int[] arr, int left, int mid, int right, int[] temp) {

        int i = left; 
        int j = mid + 1; 
        int t = 0; 
        while (i <= mid && j <= right) {
            if(arr[i] <= arr[j]) {
                temp[t] = arr[i];
                t += 1;
                i += 1;
            } else { 
                temp[t] = arr[j];
                t += 1;
                j += 1;
            }
        }
        while( i <= mid) {
            temp[t] = arr[i];
            t += 1;
            i += 1;
        }

        while( j <= right) {
            temp[t] = arr[j];
            t += 1;
            j += 1;
        }

        t = 0;
        int tempLeft = left; 
        while(tempLeft <= right) {
            arr[tempLeft] = temp[t];
            t += 1;
            tempLeft += 1;
        }

    }

总结

最后,我们创建了一个长度为1000w的数组,进行速度测试,看看最终的运行时间是多少:

java 性能 排序 java效率最高的排序算法_算法_06

 

可以看到速度非常快,下次使用排序的时候,就可以用这些比较高效的排序方法了。