欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java實現(xiàn)快速排序圖文詳解

 更新時間:2021年08月10日 15:12:24   作者:腳丫先生  
網(wǎng)上關于快速排序的算法原理和算法實現(xiàn)都比較多,不過java是實現(xiàn)并不多,而且部分實現(xiàn)很難理解,和思路有點不搭調(diào)。所以整理了這篇文章。如果有不妥之處還請建議

高快省的排序算法

有沒有既不浪費空間又可以快一點的排序算法呢?那就是“快速排序”啦!光聽這個名字是不是就覺得很高端呢。

假設我們現(xiàn)在對“6 1 2 7 9 3 4 5 10 8”這個10個數(shù)進行排序。首先在這個序列中隨便找一個數(shù)作為基準數(shù)(不要被這個名詞嚇到了,就是一個用來參照的數(shù),待會你就知道它用來做啥的了)。為了方便,就讓第一個數(shù)6作為基準數(shù)吧。接下來,需要將這個序列中所有比基準數(shù)大的數(shù)放在6的右邊,比基準數(shù)小的數(shù)放在6的左邊,類似下面這種排列:

3 1 2 5 4 6 9 7 10 8

在初始狀態(tài)下,數(shù)字6在序列的第1位。我們的目標是將6挪到序列中間的某個位置,假設這個位置是k。現(xiàn)在就需要尋找這個k,并且以第k位為分界點,左邊的數(shù)都小于等于6,右邊的數(shù)都大于等于6。想一想,你有辦法可以做到這點嗎?

排序算法顯神威

方法其實很簡單:分別從初始序列“6 1 2 7 9 3 4 5 10 8”兩端開始“探測”。先從右往左找一個小于6的數(shù),再從左往右找一個大于6的數(shù),然后交換他們。這里可以用兩個變量i和j,分別指向序列最左邊和最右邊。我們?yōu)檫@兩個變量起個好聽的名字“哨兵i”和“哨兵j”。剛開始的時候讓哨兵i指向序列的最左邊(即i=1),指向數(shù)字6。讓哨兵j指向序列的最右邊(即=10),指向數(shù)字。

這里寫圖片描述

首先哨兵j開始出動。因為此處設置的基準數(shù)是最左邊的數(shù),所以需要讓哨兵j先出動,這一點非常重要(請自己想一想為什么)。哨兵j一步一步地向左挪動(即j–),直到找到一個小于6的數(shù)停下來。接下來哨兵i再一步一步向右挪動(即i++),直到找到一個數(shù)大于6的數(shù)停下來。最后哨兵j停在了數(shù)字5面前,哨兵i停在了數(shù)字7面前。

這里寫圖片描述

這里寫圖片描述

現(xiàn)在交換哨兵i和哨兵j所指向的元素的值。交換之后的序列如下:

6 1 2 5 9 3 4 7 10 8

這里寫圖片描述

這里寫圖片描述

到此,第一次交換結束。接下來開始哨兵j繼續(xù)向左挪動(再友情提醒,每次必須是哨兵j先出發(fā))。他發(fā)現(xiàn)了4(比基準數(shù)6要小,滿足要求)之后停了下來。哨兵i也繼續(xù)向右挪動的,他發(fā)現(xiàn)了9(比基準數(shù)6要大,滿足要求)之后停了下來。此時再次進行交換,交換之后的序列如下:

6 1 2 5 4 3 9 7 10 8

第二次交換結束,“探測”繼續(xù)。哨兵j繼續(xù)向左挪動,他發(fā)現(xiàn)了3(比基準數(shù)6要小,滿足要求)之后又停了下來。哨兵i繼續(xù)向右移動,糟啦!此時哨兵i和哨兵j相遇了,哨兵i和哨兵j都走到3面前。說明此時“探測”結束。我們將基準數(shù)6和3進行交換。交換之后的序列如下:

3 1 2 5 4 6 9 7 10 8

這里寫圖片描述

這里寫圖片描述

這里寫圖片描述

到此第一輪“探測”真正結束。此時以基準數(shù)6為分界點,6左邊的數(shù)都小于等于6,6右邊的數(shù)都大于等于6。回顧一下剛才的過程,其實哨兵j的使命就是要找小于基準數(shù)的數(shù),而哨兵i的使命就是要找大于基準數(shù)的數(shù),直到i和j碰頭為止。

OK,解釋完畢?,F(xiàn)在基準數(shù)6已經(jīng)歸位,它正好處在序列的第6位。此時我們已經(jīng)將原來的序列,以6為分界點拆分成了兩個序列,左邊的序列是“3 1 2 5 4”,右邊的序列是“9 7 10 8”。接下來還需要分別處理這兩個序列。因為6左邊和右邊的序列目前都還是很混亂的。不過不要緊,我們已經(jīng)掌握了方法,接下來只要模擬剛才的方法分別處理6左邊和右邊的序列即可。現(xiàn)在先來處理6左邊的序列現(xiàn)吧。

左邊的序列是“3 1 2 5 4”。請將這個序列以3為基準數(shù)進行調(diào)整,使得3左邊的數(shù)都小于等于3,3右邊的數(shù)都大于等于3。好了開始動筆吧

如果你模擬的沒有錯,調(diào)整完畢之后的序列的順序應該是:

2 1 3 5 4

OK,現(xiàn)在3已經(jīng)歸位。接下來需要處理3左邊的序列“2 1”和右邊的序列“5 4”。對序列“2 1”以2為基準數(shù)進行調(diào)整,處理完畢之后的序列為“1 2”,到此2已經(jīng)歸位。序列“1”只有一個數(shù),也不需要進行任何處理。至此我們對序列“2 1”已全部處理完畢,得到序列是“1 2”。序列“5 4”的處理也仿照此方法,最后得到的序列如下:

1 2 3 4 5 6 9 7 10 8

對于序列“9 7 10 8”也模擬剛才的過程,直到不可拆分出新的子序列為止。最終將會得到這樣的序列,如下

1 2 3 4 5 6 7 8 9 10

到此,排序完全結束。細心的同學可能已經(jīng)發(fā)現(xiàn),快速排序的每一輪處理其實就是將這一輪的基準數(shù)歸位,直到所有的數(shù)都歸位為止,排序就結束了。下面上個霸氣的圖來描述下整個算法的處理過程。

這里寫圖片描述

這是為什么呢?

快速排序之所比較快,因為相比冒泡排序,每次交換是跳躍式的。每次排序的時候設置一個基準點,將小于等于基準點的數(shù)全部放到基準點的左邊,將大于等于基準點的數(shù)全部放到基準點的右邊。這樣在每次交換的時候就不會像冒泡排序一樣每次只能在相鄰的數(shù)之間進行交換,交換的距離就大的多了。因此總的比較和交換次數(shù)就少了,速度自然就提高了。當然在最壞的情況下,仍可能是相鄰的兩個數(shù)進行了交換。因此快速排序的最差時間復雜度和冒泡排序是一樣的都是O(N2),它的平均時間復雜度為O(NlogN)。其實快速排序是基于一種叫做“二分”的思想。我們后面還會遇到“二分”思想,到時候再聊。先上代碼,如下

代碼實現(xiàn):

public class QuickSort {
    public static void quickSort(int[] arr,int low,int high){
        int i,j,temp,t;
        if(low>high){
            return;
        }
        i=low;
        j=high;
        //temp就是基準位
        temp = arr[low];
        while (i<j) {
            //先看右邊,依次往左遞減
            while (temp<=arr[j]&&i<j) {
                j--;
            }
            //再看左邊,依次往右遞增
            while (temp>=arr[i]&&i<j) {
                i++;
            }
            //如果滿足條件則交換
            if (i<j) {
                t = arr[j];
                arr[j] = arr[i];
                arr[i] = t;
            }
        }
        //最后將基準為與i和j相等位置的數(shù)字交換
         arr[low] = arr[i];
         arr[i] = temp;
        //遞歸調(diào)用左半數(shù)組
        quickSort(arr, low, j-1);
        //遞歸調(diào)用右半數(shù)組
        quickSort(arr, j+1, high);
    }

    public static void main(String[] args){
        int[] arr = {10,7,2,4,7,62,3,4,2,1,8,9,19};
        quickSort(arr, 0, arr.length-1);
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

輸出為
1
2
2
3
4
4
7
7
8
9
10
19
62

總結

本篇文章就到這里了,希望能給你帶來幫助,也希望您能夠多多關注腳本之家的更多內(nèi)容!

相關文章

  • struts2自定義攔截器的示例代碼

    struts2自定義攔截器的示例代碼

    本篇文章主要介紹了struts2自定義攔截器的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • 在Map中實現(xiàn)key唯一不重復操作

    在Map中實現(xiàn)key唯一不重復操作

    這篇文章主要介紹了在Map中實現(xiàn)key唯一不重復操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • linux下執(zhí)行java程序的sh腳本分享

    linux下執(zhí)行java程序的sh腳本分享

    這篇文章主要介紹了linux下執(zhí)行java程序的sh腳本,僅供參考,但是設置的時候環(huán)境變量是最重要的,我就是環(huán)境變量一直不對,總是按網(wǎng)上查到的來,不明白怎么回事,才一直出錯,其實環(huán)境變量就是你要執(zhí)行的java程序所在的位置
    2014-09-09
  • java8 統(tǒng)計字符串字母個數(shù)的幾種方法總結(推薦)

    java8 統(tǒng)計字符串字母個數(shù)的幾種方法總結(推薦)

    下面小編就為大家分享一篇java8 統(tǒng)計字符串字母個數(shù)的幾種方法總結(推薦),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來吧
    2017-11-11
  • Java內(nèi)存劃分:運行時數(shù)據(jù)區(qū)域

    Java內(nèi)存劃分:運行時數(shù)據(jù)區(qū)域

    聽說Java運行時環(huán)境的內(nèi)存劃分是挺進BAT的必經(jīng)之路,這篇文章主要給大家介紹了關于Java運行時數(shù)據(jù)區(qū)域(內(nèi)存劃分)的相關資料,需要的朋友可以參考下
    2021-07-07
  • SpringBoot項目配置postgresql數(shù)據(jù)庫完整步驟(配置多數(shù)據(jù)源)

    SpringBoot項目配置postgresql數(shù)據(jù)庫完整步驟(配置多數(shù)據(jù)源)

    PostgreSQL是一種特性非常齊全的自由軟件的對象-關系型數(shù)據(jù)庫管理系統(tǒng)(ORDBMS),下面這篇文章主要給大家介紹了關于SpringBoot項目配置postgresql數(shù)據(jù)庫(配置多數(shù)據(jù)源)的相關資料,需要的朋友可以參考下
    2023-05-05
  • Spring詳細解讀事務管理

    Spring詳細解讀事務管理

    Spring事務的本質(zhì)就是對數(shù)據(jù)庫事務的支持,沒有數(shù)據(jù)庫事務,Spring是無法提供事務功能的。Spring只提供統(tǒng)一的事務管理接口,具體實現(xiàn)都是由數(shù)據(jù)庫自己實現(xiàn)的,Spring會在事務開始時,根據(jù)當前設置的隔離級別,調(diào)整數(shù)據(jù)庫的隔離級別,由此保持一致
    2022-04-04
  • Spring初始化與銷毀順序案例演示詳解

    Spring初始化與銷毀順序案例演示詳解

    這篇文章主要介紹了SpringBoot中的Bean的初始化與銷毀順序,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • SpringCloud連接不上遠程Nacos問題排查

    SpringCloud連接不上遠程Nacos問題排查

    本文主要介紹了SpringCloud連接不上遠程Nacos問題排查,可能是因為未開放端口,或集群內(nèi)部通信異常等,下面就來介紹一下問題解決,感興趣的可以了解一下
    2024-06-06
  • 一文了解Spring中攔截器的原理與使用

    一文了解Spring中攔截器的原理與使用

    在web開發(fā)中,攔截器是經(jīng)常用到的功能。它可以幫我們預先設置數(shù)據(jù)以及統(tǒng)計方法的執(zhí)行效率等等。今天就來詳細的談一下spring中的攔截器,需要的可以參考一下
    2022-06-06

最新評論