各种排序算法详解与运行时间比较---Java

有一天与室友聊天,他说自己用了冒泡排序算法来比较两个类,几年前了解过,但我现在突然不知道什么是冒泡排序了,于是准备再简单看看。

抽了个周末敲了些代码,发现挺考验编程能力的,因为需要不时提防指针越界的错误。

比较了各个排序算法的运行时间:

import java.util.Random;


/**
*@author: Zhen Chen
*@email: 15011074486@163.com
*@date: Jul 21, 2018---6:26:37 PM
*@description:  a sorting class for testing different sorting algorithm
*/


public class Sort {

    /**
     * testing different sorting algorithm
     * @param size of the test array
     */
    public static void compareSortAlgo(int size) {
        int start = 10; int end = 10000; double[] temp; long time;
        Random random = new Random();
        double[] testArray = random.doubles(size, start, end).toArray();
        temp = testArray.clone();
        time = System.currentTimeMillis();
        BubbleSort.sort(temp);
        System.out.println("time for bubble sort is " + (System.currentTimeMillis() - time) + "ms");
        temp = testArray.clone();
        time = System.currentTimeMillis();
        InsertSort.sort(temp);
        System.out.println("time for insert sort is " + (System.currentTimeMillis() - time) + "ms");
        temp = testArray.clone();
        time = System.currentTimeMillis();
        ShellSort.sort(temp);
        System.out.println("time for shell sort is " + (System.currentTimeMillis() - time) + "ms");
        temp = testArray.clone();
        time = System.currentTimeMillis();
        MergeSort.aux = temp.clone();
        MergeSort.sort(temp);
        System.out.println("time for merge sort is " + (System.currentTimeMillis() - time) + "ms");
        temp = testArray.clone();
        time = System.currentTimeMillis();
        QuickSort.sort(temp);
        System.out.println("time for quick sort is " + (System.currentTimeMillis() - time) + "ms");     
    }


    public static void main(String[] args) {                        
        int size  = 200000;
        compareSortAlgo(size);
    }

}

输出:
time for bubble sort is 55171ms
time for insert sort is 19282ms
time for shell sort is 40ms
time for merge sort is 19ms
time for quick sort is 48ms

可以发现:
归并排序最快,而希尔排序与快速排序也比较快。

1. 冒泡排序(Bubble sort)

冒泡排序是最直觉的比较算法了,它的思想是:

将相邻的元素两两比较,若顺序不对则交换顺序,直到没有需要交换的数对为止。

算法复杂度 O(n2) O ( n 2 ) ,举例:排序 (5 1 4 2)
第一轮:
( 5 1 4 2) ( 1 5 4 2 ) 交换
(1 5 4 2) (1 4 5 2 ) 交换
(1 4 5 2) (1 4 2 5 ) 交换

第二轮:
(1 4 2 5 ) (1 4 2 5)
(1 4 2 5) (1 2 4 5) 交换

第三轮:
(1 2 4 5) (1 2 4 5)

java 代码:

import java.util.Arrays;

/**
*@author: Zhen Chen
*@email: 15011074486@163.com
*@date: Jul 20, 2018---6:10:24 PM
*@description:  a bubble sorting algorithm in Java
*/

public class BubbleSort {

    public static sort(double[] a) {
        int n = a.length;
        for (int i = 0; i < n - 1; i++)
            for (int j = 0; j < n - i - 1; j++) {
                if (a[j] > a[j + 1]) {
                    double temp = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = temp;
                }
            }
    }

    public static void main(String[] args) {
        double[] a = {8, 3, 2, 5};
        sort(a);
        System.out.println(Arrays.toString(a));

    }
}
2. 插入排序

基本思想类似于扑克牌的起牌,总是将后一个元素插入到前面有序的数组中。

算法复杂度: O(n2) O ( n 2 )
java 代码:

/**
*@author: Zhen Chen
*@email: 15011074486@163.com
*@date: Jul 21, 2018---8:41:58 PM
*@description:  an inserting algorithm
*/

public class InsertSort {

    public static void sort(double[] a) {
        int n = a.length;       
        for (int i = 1; i < n; i++) {
            // input a[i] to a[0], a[1], ..., a[i-1] 
            double key = a[i];
            int j = i - 1;
            while (j >= 0 && a[j] > key) {
                a[j + 1] = a[j];  // bigger element back one position
                j--;
            }
            a[j + 1] = key;
        }
    }

    public static void main(String[] args) {
        double[] a = {1, 4, 8, 2, 55, 3, 4, 8, 6, 4, 0, 11, 34, 90, 23, 54, 77, 9, 2, 9, 4, 10};
        sort(a);
        System.out.println(Arrays.toString(a));

    }

}
3. 希尔排序

该排序是插入排序的扩展,基本思想是: 使数组中任意间隔为 h h 的元素都是有序的。

算法复杂度为: O(n3/2) O(n4/3) O ( n 4 / 3 ) ,算法复杂度的证明比较复杂,与数列 h h 的选择有关。
java 代码:

import java.util.Arrays;

/**
*@author: Zhen Chen
*@email: 15011074486@163.com
*@date: 2018年7月22日---下午2:28:30
*@description:  algorithm code for shell sorting
*/

public class ShellSort {

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

    public static void sort(double[] a) {
        int n = a.length;
        int h = 1;
        while (h < n/3) h= 3*h + 1;

        while (h > 0) {
            for (int i = h; i < n; i++) {
                // insert h sort
                double keyValue = a[i];
                int j = i - h;          
                while (j >= 0 && a[j] > keyValue) {
                    a[j + h] = a[j];
                    j -= h;         
                }   
                a[j + h] = keyValue;        
            }
            h = h/3;
        }
    }

    public static void main(String[] args) {
        double[] a = {1, 4, 8, 2, 55, 3, 4, 8, 6, 4, 0, 11, 34, 90, 23, 54, 77, 9, 2, 9, 4, 10};
        sort(a);
        System.out.println(Arrays.toString(a));
    }

}
4. 归并排序

归并排序的思想是:利用二分法,将一个数组分成两个子数组,对每个子数组分别排序,然后将排序好的子数组合并。
注意:该算法需要一个辅助数组,为了加快运算速度,在分治之前就应该定义初始化好辅助数组,否则在子数组中频繁初始化辅助数组,就会大大增加计算时间。

算法复杂度:O(nlgn)
注:将一个数组用二分法,共有 lgn lg ⁡ n 层,没一层有 n n 次比较,因此得出该算法复杂度。

java 代码:

import java.util.Arrays;

/**
*@author: Zhen Chen
*@email: 15011074486@163.com
*@date: 2018年7月22日---下午7:17:11
*@description:  merging sorting algorithm
*/

public class MergeSort {
    static double[] aux; 

    public static void sort(double[] a) {
        mergeSort(a, 0, a.length - 1);
    }

    static void mergeSort(double[] a, int low, int high) {
        if (low >= high)
            return;
        else {
            int mid = (low + high)/2;
            mergeSort(a, low, mid);
            mergeSort(a, mid + 1, high);
            merge(a, low, mid, high);
        }
    }

    static void merge(double[] a, int low, int mid, int high) {
        int i = low;
        int j = mid + 1;


        for (int k = low; k <= high; k++) {
            if(i > mid)  a[k] = aux[j++];
            else if (j > high) a[k] = aux[i++];
            else if (aux[i] > aux[j]) a[k] = aux[j++];
            else                 a[k] = aux[i++];       
        }
    }


    public static void main(String[] args) {
        double[] a = {1, 4, 8, 2, 55, 3, 4, 8, 6, 4, 0, 11, 34, 90, 23, 54, 77, 9, 2, 9, 4, 10};
        aux = a.clone();
        sort(a);
        System.out.println(Arrays.toString(a));

    }

}

5. 快速排序

快速排序是 java 默认的排序算法,其基本思想是:

1. 从数列中调出一个元素作为基准;
2. 对基准元素左侧与右侧分别扫描,将比基准元素小的放在基准元素左侧,大的放在右侧;
3. 基准元素左右两端得到了两个子数列,对子数列重复以上步骤。

其算法复杂度为 O(nlg(n))
代码:


import java.util.Arrays;
import java.util.Random;


/**
*@author: Zhen Chen
*@email: 15011074486@163.com
*@date: Jul 20, 2018---8:45:51 PM
*@description:  a quick sort algorithm in Java
*/

public class QuickSort {

    /**
     *  shuffle an array before sorting,
     *  eliminate input dependent 
     *  
     * @param a
     * @return
     */
    static void shuffle(double[] a) {
        Random random = new Random();
        for (int i = 0; i< a.length; i++) {
            int j = random.nextInt(0, i + 1);
            double temp = a[i];
            a[i] = a[j];
            a[j] = temp;
        }
    }

    public static void sort(double[] a) {
        shuffle(a);
        quickSort(a, 0, a.length - 1);
    }

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

    public static void quickSort(double[] a, int start, int end) {
        int k = (start + end)/2;
        if (start >= end)
            return;
        else {
            // step 1
            int i = start; int j = end; double baseValue = a[k];

            // setp 2
            while (i < j) {
                while (a[i] < baseValue) { // until find a value that greater than baseValue
                    i ++;
                    if (i >= end)
                        break;
                }

                while (a[j] > baseValue) { // until find a value that less than baseValue
                    j --;
                    if (j <= start)
                        break;
                }               
                exchange(a, i, j); 
                if (a[i] == a[j]) // avoid endless loop
                    i++;
            }

            // setp 3
            quickSort(a, start, j - 1);
            quickSort(a, j + 1, end);
        }

    }

    public static void main(String[] args) {
        double[] a = {1.0, 4.0, 8.0, 9.0, 3.0, 4.0};
        sort(a);
        System.out.println(Arrays.toString(a));

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心态与习惯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值