java實(shí)現(xiàn)的比較不錯(cuò)的快速排序

本文為原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明出處宵膨,謝謝你……
喜歡java并發(fā)編程的請(qǐng)加群:736156823
開(kāi)始-->

import java.util.concurrent.ThreadLocalRandom;

public class QSort {

    // 選擇樞軸時(shí)候要求數(shù)據(jù)個(gè)數(shù)大于3
    private static final int OFF_SIT = 3;
    // 選擇快排還是插入的界限
    private static final int INSERT_FLAG = 13;

    // 數(shù)組的有效下標(biāo)
    public void sort(int[] array, int left, int right) {
        // 一些無(wú)用的校驗(yàn)
        if (null == array) {
            return;
        } else if (array.length <= 1) {
            return;
        } else if (left < 0 || right < 0) {
            return;
        } else if (right - left <= 1) {
            return;
        } else {
            quick(array, left, right);
        }
    }

    private void quick(int[] array, int left, int right) {
        // 如果數(shù)組中的數(shù)據(jù)太少皱炉,使用插入排序
        // 根據(jù)下面選擇樞軸的方法,太少也是不允許的
        // 大量實(shí)驗(yàn)證明,數(shù)據(jù)在5到20內(nèi)的數(shù)據(jù)另萤,插入排序快于快速排序
        // 這里選擇的是13梯影,實(shí)驗(yàn)發(fā)現(xiàn)13比較好
        if (left + OFF_SIT <= right) {
            if (left + INSERT_FLAG <= right) {
                int p = partition(array, left, right);
                // 實(shí)際比較是從left-1巫员,right-2開(kāi)始的
                // 因?yàn)閘eft,right-1甲棍,right三者已經(jīng)有序
                // 具體參考樞軸的選擇策略partition
                int i = left, j = right - 1;
                for (; ; ) {
                    for (; ; ) {
                        // 直接加就好了简识,不需要判斷是否越界
                        // 原因就是有三個(gè)數(shù)已經(jīng)控制了邊界
                        i = i + 1;
                        // 這里說(shuō)明下:
                        // 為什么大于或者等于都要停止指針移動(dòng)?
                        // 因?yàn)榇罅繉?shí)驗(yàn)發(fā)現(xiàn),當(dāng)?shù)扔诘臅r(shí)候也停止指針移動(dòng)是較好的
                        // 從工程角度看兩個(gè)指針都要判斷等于才行
                        // 因?yàn)槿绻挥幸贿吪袛鄷?huì)造成不平衡性問(wèn)題
                        // 也就是因?yàn)榭炫琶刻硕紩?huì)分大于小于樞軸的兩個(gè)集合的
                        // 如果只有一邊判斷等于那么很容易將等于樞軸的數(shù)分到一個(gè)集合中
                        // 造成了另一個(gè)集合沒(méi)有等于樞軸的數(shù)
                        // 從工程學(xué)角度是不合理的
                        if (array[i] >= p) {
                            break;
                        }
                    }
                    for (; ; ) {
                        j = j - 1;
                        if (array[j] <= p) {
                            break;
                        }
                    }
                    // i>=j七扰,說(shuō)明都比較完了奢赂,應(yīng)該跳出循環(huán)
                    if (i < j) {
                        swap(array, i, j);
                    } else {
                        break;
                    }
                }
                // {left,2,3,4,5,i,i+1,8,9,right-1,right}
                // 對(duì)照數(shù)組就很明了了
                swap(array, i, right - 1);
                // 是一個(gè)遞歸調(diào)用,后續(xù)考慮實(shí)現(xiàn)非遞歸調(diào)用的高效算法
                // 因?yàn)槭且獙?shí)現(xiàn)并發(fā)的快排的
                quick(array, left, i - 1);
                quick(array, i + 1, right);
            } else {
                insertion(array, left, right);
            }
        } else {
            insertion(array, left, right);
        }
    }

    // 樞軸的選擇颈走,采用中位數(shù)法
    // 1)對(duì)頭膳灶,中,尾三個(gè)數(shù)進(jìn)行排序
    // 2)將已經(jīng)排好序的中間位置的數(shù)與倒數(shù)第二個(gè)數(shù)交換
    // 3)這樣做的好處是:排序的部分就是第二個(gè)位置與倒數(shù)第三個(gè)位置的中間部分
    // 中間沒(méi)有樞軸立由,移動(dòng)指針的時(shí)候無(wú)需判斷越界
    // 因?yàn)閮蛇叺倪吔缫呀?jīng)確定了
    // 這樣還有個(gè)好處就是數(shù)組中已經(jīng)有三個(gè)數(shù)的排好序的了
    // 并且這三個(gè)數(shù)不需要參與移動(dòng)
    // 僅僅作為一些判斷標(biāo)志以及控制
    private int partition(int[] array, int left, int right) {
        int c = (left + right) / 2;
        if (array[left] > array[c]) {
            swap(array, left, c);
        }
        if (array[left] > array[right]) {
            swap(array, left, right);
        }
        if (array[c] > array[right]) {
            swap(array, c, right);
        }
        swap(array, c, right - 1);
        return array[right - 1];
    }

    private void swap(int[] array, int left, int right) {
        int temp = array[left];
        array[left] = array[right];
        array[right] = temp;
    }

    // 插入排序
    public void insertion(int[] array, int left, int right) {
        first(array, left, right);
        for (int i = left + 2; i <= right; i++) {
            int temp = array[i];
            int j = i;
            for (; temp < array[j - 1]; j--) {
                array[j] = array[j - 1];
            }
            array[j] = temp;
        }
    }

    // 這里的選擇最小數(shù)也是控制手段轧钓,簡(jiǎn)單的選擇,并不是像冒泡那樣
    // 正確方法還是參考之前的具體算法吧
    private void first(int[] array, int left, int right) {
        int sm = left;
        for (int i = left; i <= right; i++) {
            if (array[i] < array[sm]) {
                sm = i;
            }
        }
        // 僅僅將最小的數(shù)置于最開(kāi)始的位置
        swap(array, left, sm);
    }

    // 至于時(shí)間復(fù)雜度锐膜,空間復(fù)雜度大家百度吧毕箍,或者參考算法導(dǎo)論
    public static void main(String args[]) {
        QSort qs = new QSort();
        // 每次都是生成的不同的隨機(jī)數(shù)
        // 如果使用同一組數(shù),這樣利用硬件特性道盏,耗費(fèi)的時(shí)間會(huì)更少
        // 可以試試
        ThreadLocalRandom random = ThreadLocalRandom.current();
        for (int t = 0; t < 100; t++) {
            int nums[] = new int[99999999];
            for (int i = 0; i < 99999999; i++) {
                int r = random.nextInt(999999999);
                nums[i] = r;
            }
            System.out.println("quick sort init finish ......");
            //qs.insertion(nums,0,nums.length-1);
            long start = System.nanoTime();
            qs.sort(nums, 0, nums.length - 1);
            long finish = System.nanoTime();
            System.out.println("quick sort finish ......cust nano time=" + (finish - start));
            for (int i = 0; i < nums.length - 1; i++) {
                if (nums[i] > nums[i + 1]) {
                    throw new IllegalStateException();
                }
            }
            System.out.println("...... check finish ,time=" + t + ",  ......");
        }
    }

}

喜歡java并發(fā)編程的請(qǐng)加群:736156823

<--結(jié)束
有問(wèn)題歡迎指正而柑,這是新鮮出爐的
本文為原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明出處荷逞,謝謝你……

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末媒咳,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子颅围,更是在濱河造成了極大的恐慌伟葫,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件院促,死亡現(xiàn)場(chǎng)離奇詭異筏养,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)常拓,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門渐溶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人弄抬,你說(shuō)我怎么就攤上這事茎辐。” “怎么了掂恕?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵拖陆,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我懊亡,道長(zhǎng)依啰,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任店枣,我火速辦了婚禮速警,結(jié)果婚禮上叹誉,老公的妹妹穿的比我還像新娘。我一直安慰自己闷旧,他們只是感情好长豁,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著忙灼,像睡著了一般匠襟。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上缀棍,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天宅此,我揣著相機(jī)與錄音,去河邊找鬼爬范。 笑死,一個(gè)胖子當(dāng)著我的面吹牛弱匪,可吹牛的內(nèi)容都是我干的青瀑。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼萧诫,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼斥难!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起帘饶,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤哑诊,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后及刻,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體镀裤,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年缴饭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了暑劝。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡颗搂,死狀恐怖担猛,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情丢氢,我是刑警寧澤傅联,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站疚察,受9級(jí)特大地震影響蒸走,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜稍浆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一载碌、第九天 我趴在偏房一處隱蔽的房頂上張望猜嘱。 院中可真熱鬧,春花似錦嫁艇、人聲如沸朗伶。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)论皆。三九已至,卻和暖如春猾漫,著一層夾襖步出監(jiān)牢的瞬間点晴,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工悯周, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留粒督,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓禽翼,卻偏偏與公主長(zhǎng)得像屠橄,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子闰挡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,071評(píng)論 25 707
  • 請(qǐng)讓我看看你的手 你的手猶如生滿鐵銹 原本濕潤(rùn)的皮膚與氧氣廝磨 與老繭相守 你撐起了這個(gè)家 卻嶙峋了雙手 請(qǐng)讓我看...
    填我十萬(wàn)八千夢(mèng)閱讀 310評(píng)論 0 9
  • 娟子在結(jié)束了繁忙的一天的醫(yī)院工作长酗,就奔赴了閨蜜佳麗的約溪北,看著梨花帶雨的標(biāo)準(zhǔn)的鵝蛋臉,娟子知道夺脾,這次之拨,佳麗是真真的傷...
    漂泊的思念閱讀 540評(píng)論 0 6
  • 新年開(kāi)跑第一天 2019年核心目標(biāo):變美 變瘦 變有錢! 每天只做三件事 :吃飯 睡覺(jué) 上首席劳翰!
    美力私教森森張閱讀 189評(píng)論 1 0