快速排序算法

想必大多數程序員接觸的第一種排序算法是冒泡排序,冒泡排序的特色是:邏輯簡單,實現起來也不難,但在數據量比較大的時候性能比較低。java

以數字由大到小的排序爲例,寫一個簡單的冒泡排序。程序員

/**
 * 冒泡排序
 * Created by Administrator on 2017/4/4.
 */
public class BubblingSortArithmetic {
    /**
     * 冒泡排序實現
     * @param array
     */
    public static void bubblingSort(int[] array){
        int temp;
        for (int i = 0; i < array.length-1; i++) {
            for (int j = 0; j < array.length-i-1; j++) {
                if(array[j] > array[j+1]){
                    temp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = temp;
                }
            }

        }
    }
}

 

咱們看到,冒泡排序就是兩個for循環嵌套,內層循環再加一個if語句作邏輯判斷。redis

通俗點解釋冒泡排序就是:外層循環控制冒泡的趟數(數組長度-1),內層循環控制一趟冒泡過程當中數組相鄰兩個元素的比較次數及最大索引位,而且一趟冒泡把此次排序中最大的那個數放到最大索引位處。算法

冒泡排序性能低的緣由是:每一次排序只能計算出最大的數,並且下次排序對數組的切分減一,這樣在數據量較大的時候,性能上的劣勢就顯現出來了。數組

下面咱們來談一下快速排序這種算法:dom

首先,快速排序算法是對冒泡排序算法的一種改進其思想是:選擇數組中的一個元素做爲中位數(通常是數組中第一個元素),經過一趟冒泡把整個數組分紅兩部分,左邊的部分都比該中位數小,右邊的部分都比該中位數大,而後經過遞歸的方式分別對上次排序分紅的兩部分數組進行排序,直到整個數組有序爲止。工具

從整個排序流程上看,快速排序算法一次排序就能夠把整個數組分紅一大一小兩部分,並且對數組的切分使用了二分的原理,這也是快速排序性能好,速度快的緣由。性能

雖然快速排序算法思想理解起來很簡單就是把一次排序中做爲中位數的那個元素"放中間",讓左邊的元素比它小右邊的元素比它大,看似簡單但實現起來並非那麼容易。幸運的是已經有前人對這種算法有了很好的實現,對於快速排序算法的實現,個人理解是:選定數組第一個元素做爲key(中位數),當狀態值爲true時與高位比大,當狀態值爲false時與低位比小,兩頭數組的下標(i,j)往中間湊,直到i=j時,一次排序結束,接下來使用遞歸分別對中位數兩側的數組進行上述的排序規則。測試

下面以如下數組第一次排序爲例,經過一張圖來講明這一過程。ui

int[] arrays = {34,15,66,58,66,27,22};

 下面是快速排序算法代碼實現:

package com.opensource.arithmetic.sort;

/**
 * 快速排序算法
 */
public class QuickSortArithmetic {

    /**
     * 快速排序算法入口
     * @param arrays
     * @param lenght
     */
    public static void sort_entrance(int[] arrays, int lenght) {

        if (null == arrays || lenght < 1) {
            System.out.println("input error!");
            return;
        }
        quick_sort(arrays, 0, lenght - 1);
    }

    /**
     * 快速算法實現
     * @param arrays
     * @param start
     * @param end
     */
    public static void quick_sort(int[] arrays, int start, int end) {

        if(start>=end){
            return;
        }
        int i = start;
        int j = end;
        int key = arrays[i];
        boolean flag = true;
        while (i != j) {
            if (flag) {
                if (key > arrays[j]) {
                    swop(arrays, i, j);
                    flag=false;
                    i++;
                } else {
                    j--;
                }
            }else{
                if(key < arrays[i]){
                    swop(arrays, i, j);
                    flag=true;
                    j--;
                }else{
                    i++;
                }
            }
        }
        quick_sort(arrays, start, j-1);
        quick_sort(arrays, i+1, end);

    }

    /**
     * 用於數組中兩個元素之間的交換
     * @param arrays
     * @param i
     * @param j
     */
    private static void swop(int[] arrays, int i, int j) {
        int temp;
        temp = arrays[i];
        arrays[i] = arrays[j];
        arrays[j] = temp;
    }

}

下面咱們以長度爲100000,數組元素在0~1000範圍內的數組中爲例,對冒泡排序和快速的性能作一下測試。

首先咱們把用於測試的數據放入redis中,這是作一是爲了保證屢次測試時數據的惟一性,二是防止數據量過大形成的棧溢出。

生成隨機數組的工具類:

package com.opensource.arithmetic.util;

import java.util.Random;

/**
 * Created by Administrator on 2017/4/4.
 */
public class RandomUtils {

    private static Random random = new Random();

    /**
     * 用於生成scope之內,長度爲length的隨機數組。
     * @param length
     * @param scope
     * @return
     */
    public static int[] getArrays(int length,int scope){
        int[] arrays = new int[length];
        for (int i=0; i<length; i++){
            arrays[i] = random.nextInt(scope);
        }
        return arrays;
    }
}

字符串和int類型數組轉換的工具類:

package com.opensource.arithmetic.util;

import java.util.Arrays;

/**
 * Created by Administrator on 2017/4/4.
 */
public class StringUtils {
    /**
     * 用於數組轉換字符串後首尾「[","]"切割
     * @param arrays
     * @return
     */
    public static String getArrayToString(int[] arrays){

        String str = Arrays.toString(arrays);
        return str.substring(1,str.length()-1);

    }

    /**
     * 用於把字符串轉換爲int類型數組
     * @param str
     * @return
     */
    public static int[] getStringToArrays(String str){

        String[] strArray = str.split(", ");//這裏以逗號加空格切分字符串,空格必定不能少。
        int length = strArray.length;
        int[] arrays = new int[length];
        for (int i = 0; i <length ; i++) {
            arrays[i] = Integer.parseInt(strArray[i]);
        }
        return arrays;

    }
}

把數據存入redis

package com.opensource.arithmetic.util;

import redis.clients.jedis.Jedis;

import java.util.Arrays;

/**
 * Created by Administrator on 2017/4/4.
 */
public class RedisUtil {
    public static Jedis jedis = new Jedis("localhost", 6379);

    /**
     * 向redis中存入數據
     * @param key
     * @param value
     */
    public static void setData(String key,String value){
        jedis.set(key,value);
    }


    public static String getData(String kye){
        return jedis.get(kye);
    }


    public static void main(String[] args) {

        int[] testArrays = RandomUtils.getArrays(100000,1000);
        String StrArrays = StringUtils.getArrayToString(testArrays);
        setData("arrays",StrArrays);
    }

}

測試類:

package com.opensource.arithmetic.test;

import com.opensource.arithmetic.sort.BubblingSortArithmetic;
import com.opensource.arithmetic.sort.QuickSortArithmetic;
import com.opensource.arithmetic.util.RedisUtil;
import com.opensource.arithmetic.util.StringUtils;

/**
 * Created by Administrator on 2017/4/4.
 */
public class Test {
    

    public static void main(String[] args) {

        String StrData = RedisUtil.getData("arrays");
        int[] arrays =  StringUtils.getStringToArrays(StrData);

        long start = System.currentTimeMillis();
        QuickSortArithmetic.quickSort(arrays,arrays.length);
        //BubblingSortArithmetic.bubblingSort(arrays);
        System.out.println( System.currentTimeMillis()-start);
    }
}

使用冒泡排序,對arrays數組排序時間在27.5秒左右。

使用快速排序,對arrays數組排序時間在0.047秒左右。

 

最後說一點,咱們做爲程序員,研究問題仍是要仔細深刻一點的。當你對原理了解的有夠透徹,開發起來也就駕輕就熟了,不少開發中的問題和疑惑也就迎刃而解了,並且在面對其餘問題的時候也可作到舉一反三。固然在開發中沒有太多的時間讓你去研究原理,開發中要以實現功能爲前提,可等項目上線的後,你有大把的時間或者空餘的時間,你大可去刨根問底,深刻的去研究一項技術,爲以爲這對一名程序員的成長是很重要的事情。

相關文章
相關標籤/搜索