數(shù)據(jù)結(jié)構(gòu)之一些常見的排序(Java)


冒泡排序

  • 算法規(guī)則: 由于算法每次都將一個(gè)最大的元素往上冒奶镶,我們可以將待排序集合(0...n)看成兩部分,一部分為(k..n)的待排序unsorted集合,另一部分為(0...k)的已排序sorted集合,每一次都在unsorted集合從前往后遍歷傅是,選出一個(gè)數(shù),如果這個(gè)數(shù)比其后面的數(shù)大威创,則進(jìn)行交換落午。完成一輪之后,就肯定能將這一輪unsorted集合中最大的數(shù)移動(dòng)到集合的最后肚豺,并且將這個(gè)數(shù)從unsorted中刪除,移入sorted中界拦。冒泡排序的時(shí)間復(fù)雜度為O(n^2)吸申。

  • 代碼實(shí)現(xiàn)(java)

public void bubbleSort(int[] data){
    //這里從數(shù)組最后面開始遍歷
    for (int i = data.length - 1; i > 0; --i) {
        //在這里體現(xiàn)出 “將每一趟排序選出來(lái)的最大的數(shù)從sorted中移除”
        for (int j = 0; j < i; j++) {
            //保證在相鄰的兩個(gè)數(shù)中比較選出最大的并且進(jìn)行交換(冒泡過(guò)程)
            if (data[j] > data[j + 1]) {
                int temp = data[j];
                data[j] = data[j + 1];
                data[j + 1] = temp;
            }
        }
    }
}

并歸排序

  • 算法規(guī)則: 像快速排序一樣,由于歸并排序也是分治算法享甸,因此可使用分治思想:
    1.申請(qǐng)空間截碴,使其大小為兩個(gè)已經(jīng)排序序列之和,該空間用來(lái)存放合并后的序列
    2.設(shè)定兩個(gè)指針蛉威,最初位置分別為兩個(gè)已經(jīng)排序序列的起始位置
    3.比較兩個(gè)指針?biāo)赶虻脑厝盏ぃx擇相對(duì)小的元素放入到合并空間,并移動(dòng)指針到下一位置
    4.重復(fù)步驟3直到某一指針到達(dá)序列尾
    5.將另一序列剩下的所有元素直接復(fù)制到合并序列尾
    空間復(fù)雜度為O(n)蚯嫌,時(shí)間復(fù)雜度為O(nlogn)哲虾。
  • 代碼實(shí)現(xiàn)(java)
public void mergeSort(int[] a, int low, int high) {
    int mid = (low + high) / 2;
    if (low < high) {
        //左邊
        mergeSort(a, low, mid);
        //右邊
        mergeSort(a, mid + 1, high);
        merge(a, low, mid, high);
    }
}

private void merge(int[] a, int low, int mid, int high) {
    int[] temp = new int[high - low + 1];
    //指向左邊的指針
    int i = low;
    //指向右邊的指針
    int j = mid + 1;
    int k = 0;
    //把較小的數(shù)先移到新數(shù)組中
    while (i <= mid && j <= high) {
        if (a[i] > a[j]) {
            temp[k++] = a[j++];
        } else {
            temp[k++] = a[i++];
        }
    }
    //左邊剩余的數(shù)據(jù)加入得到新數(shù)組
    while (i <= mid) {
        temp[k++] = a[i++];
    }
    //右邊剩余的數(shù)據(jù)加入到新數(shù)組
    while (j <= high) {
        temp[k++] = a[j++];
    }
    for (int l = 0; l < temp.length; l++) {
        a[l + low] = temp[l];
    }
}

快速排序

  • 算法規(guī)則: 本質(zhì)來(lái)說(shuō),快速排序的過(guò)程就是不斷地將無(wú)序元素集遞歸分割择示,一直到所有的分區(qū)只包含一個(gè)元素為止束凑。
    由于快速排序是一種分治算法,我們可以用分治思想將快排分為三個(gè)步驟:
    1.分:設(shè)定一個(gè)分割值栅盲,并根據(jù)它將數(shù)據(jù)分為兩部分
    2.治:分別在兩部分用遞歸的方式汪诉,繼續(xù)使用快速排序法
    3.合:對(duì)分割的部分排序直到完成
    快速排序是不穩(wěn)定的,其時(shí)間平均時(shí)間復(fù)雜度是O(nlgn)谈秫。

  • 代碼實(shí)現(xiàn)(java)

    public static int dividerAndChange(int[] args, int start, int end) {
        //參照值
        int pivot = args[start];
        while (start < end) {
            //首先從右向左查找,直到找到比參數(shù)小的第一個(gè)數(shù),然后交換位置
            while (start < end && pivot <= args[end]) {
                end--;
            }
            if (start < end) {
                //開始交換位置
                args[start] = args[end];
                start++;
            }
            //從左往右找扒寄,找到比參數(shù)大的就交換位置
            while (start < end && pivot > args[start]) {
                start++;
            }
            if (start < end) {
                //開始交換位置
                args[end] = args[start];
                end--;
            }
        }
        args[start] = pivot;
        System.out.println("start:" + start + ",end:" + end);
        return start;
    }
    
    public static void quickSort(int[] args, int start, int end) {
        if (end - start > 1) {
            int mid = dividerAndChange(args, start, end);
            //對(duì)左邊數(shù)組排序
            quickSort(args, start, mid);
            //對(duì)右邊數(shù)組排序
            quickSort(args, mid + 1, end);
        }
    }

選擇排序

  • 算法規(guī)則: 將待排序集合(0...n)看成兩部分,在起始狀態(tài)中拟烫,一部分為(k..n)的待排序unsorted集合该编,另一部分為(0...k)的已排序sorted集合,在待排序集合中挑選出最小元素并且記錄下標(biāo)i,若該下標(biāo)不等于k构灸,那么 unsorted[i] 與 sorted[k]交換 上渴,一直重復(fù)這個(gè)過(guò)程岸梨,直到unsorted集合中元素為空為止写穴。選擇排序的時(shí)間復(fù)雜度為O(n^2)

  • 代碼實(shí)現(xiàn)(java)

public void selectionSort(int[] args){
    for (int i = 0; i < args.length - 1; i++) {
        int k = i;
        for (int j = k + 1; j < args.length; j++) {
            //循環(huán)遍歷,找到最小值的下標(biāo)
            if (args[j] < args[k]) {
                k = j;
            }
        }
        if (k != i) {
            //交換args[i]和args[k]
            int temp = args[i];
            args[i] = args[k];
            args[k] = temp;
        }
    }
}

插入排序

  • 算法規(guī)則:插入排序不是通過(guò)交換位置而是通過(guò)比較找到合適的位置插入元素來(lái)達(dá)到排序的目的的寻歧。相信大家都有過(guò)打撲克牌的經(jīng)歷,特別是牌數(shù)較大的鉴未。在分牌時(shí)可能要整理自己的牌隔披,牌多的時(shí)候怎么整理呢赃份?就是拿到一張牌,找到一個(gè)合適的位置插入奢米。這個(gè)原理其實(shí)和插入排序是一樣的抓韩。舉個(gè)栗子,對(duì)5,3,8,6,4這個(gè)無(wú)序序列進(jìn)行簡(jiǎn)單插入排序鬓长,首先假設(shè)第一個(gè)數(shù)的位置時(shí)正確的谒拴,想一下在拿到第一張牌的時(shí)候,沒(méi)必要整理涉波。然后3要插到5前面英上,把5后移一位,變成3,5,8,6,4.想一下整理牌的時(shí)候應(yīng)該也是這樣吧啤覆。然后8不用動(dòng)苍日,6插在8前面,8后移一位窗声,4插在5前面相恃,從5開始都向后移一位。注意在插入一個(gè)數(shù)的時(shí)候要保證這個(gè)數(shù)前面的數(shù)已經(jīng)有序笨觅。簡(jiǎn)單插入排序的時(shí)間復(fù)雜度也是O(n^2)拦耐。
    /**
    * 插入排序
    * @param args
    * @return
    */
   public static int[] insertSort(int[] args) {
       if (args.length == 0) {
           return null;
       }

       // 默認(rèn)數(shù)組的第一個(gè)數(shù)字已經(jīng)排好序
       // 這里把第二個(gè)數(shù)字,作為拿來(lái)比較的數(shù)字.假設(shè)第一個(gè)數(shù)字位置已經(jīng)確定.然后將二個(gè)數(shù)字和第一個(gè)數(shù)字比較
       for (int i = 1; i < args.length; i++) {
           int k = i;
           //這里將未排序的第一個(gè)數(shù)字拿出來(lái)
           int target = args[i];
           /*for (k = i - 1; k >= 0 && target < args[k]; k--) {
               args[k + 1] = args[k];
           }*/
           //這里循環(huán)比較,將未排序的第一個(gè)數(shù)和前面已排序的數(shù)組循環(huán)比較
           while (k >= 0 && target < args[k - 1]) {
               args[k] = args[k - 1];
               k--;
           }
           //這里重新設(shè)置參照值.
           args[k] = target;
       }
       return args;
   }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市屋摇,隨后出現(xiàn)的幾起案子揩魂,更是在濱河造成了極大的恐慌,老刑警劉巖炮温,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件火脉,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡柒啤,警方通過(guò)查閱死者的電腦和手機(jī)倦挂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)担巩,“玉大人方援,你說(shuō)我怎么就攤上這事√伟” “怎么了犯戏?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵送火,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我先匪,道長(zhǎng)种吸,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任呀非,我火速辦了婚禮坚俗,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘岸裙。我一直安慰自己猖败,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布降允。 她就那樣靜靜地躺著恩闻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拟糕。 梳的紋絲不亂的頭發(fā)上判呕,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音送滞,去河邊找鬼。 笑死辱挥,一個(gè)胖子當(dāng)著我的面吹牛犁嗅,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播晤碘,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼褂微,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了园爷?” 一聲冷哼從身側(cè)響起宠蚂,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎童社,沒(méi)想到半個(gè)月后求厕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡扰楼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年呀癣,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片弦赖。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡项栏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蹬竖,到底是詐尸還是另有隱情沼沈,我是刑警寧澤流酬,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站列另,受9級(jí)特大地震影響芽腾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜访递,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一晦嵌、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拷姿,春花似錦惭载、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至踪古,卻和暖如春含长,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背伏穆。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工拘泞, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人枕扫。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓陪腌,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親烟瞧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子诗鸭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

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

  • 概述 排序有內(nèi)部排序和外部排序,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序参滴,而外部排序是因排序的數(shù)據(jù)很大强岸,一次不能容納全部...
    蟻前閱讀 5,167評(píng)論 0 52
  • 概述排序有內(nèi)部排序和外部排序,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序砾赔,而外部排序是因排序的數(shù)據(jù)很大蝌箍,一次不能容納全部的...
    Luc_閱讀 2,255評(píng)論 0 35
  • 概述:排序有內(nèi)部排序和外部排序,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序过蹂,而外部排序是因排序的數(shù)據(jù)很大十绑,一次不能容納全部...
    每天刷兩次牙閱讀 3,727評(píng)論 0 15
  • 前言 查找和排序算法是算法的入門知識(shí),其經(jīng)典思想可以用于很多算法當(dāng)中酷勺。因?yàn)槠鋵?shí)現(xiàn)代碼較短本橙,應(yīng)用較常見。所以在面試中...
    寶塔山上的貓閱讀 1,079評(píng)論 1 21
  • 給家庭配置保險(xiǎn)脆诉,怎么配置比較合適呢甚亭?針對(duì)不同年齡階段的人贷币,承擔(dān)的家庭責(zé)任不同,配置的保險(xiǎn)也不同亏狰。 在這里七媽得說(shuō)明...
    果果希媽閱讀 175評(píng)論 0 0