JAVA實(shí)現(xiàn)八大算法排序

一隅很、插入排序

插入排序是一種最簡(jiǎn)單直觀的排序算法叔营,它的工作原理是通過(guò)構(gòu)建有序序列所宰,對(duì)于未排序數(shù)據(jù),在已排序序列中從后向前掃描仔粥,找到相應(yīng)位置并插入。

  public static void main(String[] s) {
        int[] array = {3,1,6,0,8};
        //循環(huán)的次數(shù)谭羔,也監(jiān)控著每一輪開(kāi)始key的位置
        for (int i = 0; i < array.length - 1; i++) {
            int key = array[i + 1];
            int j;
            //一邊比較一邊為key的插入騰空位
            for (j = i; j >= 0 && key < array[j]; j--) {
                array[j + 1] = array[j];
            }
            array[j + 1] = key;
        }
        System.out.println(Arrays.toString(array));
    }

二口糕、希爾排序

希爾排序磕蛇,也稱遞減增量排序算法十办,是插入排序的一種更高效的改進(jìn)版本超棺。但希爾排序是非穩(wěn)定排序算法。
先將整個(gè)待排序的記錄序列分割成為若干子序列分別進(jìn)行直接插入排序件相,待整個(gè)序列中的記錄“基本有序”時(shí)氧苍,再對(duì)全體記錄進(jìn)行依次直接插入排序。

  public static void main(String[] args) {
        int[] arr = {3,1,6,0,8};
        //step:步長(zhǎng)
        for (int step = arr.length / 2; step > 0; step /= 2) {
            //對(duì)一個(gè)步長(zhǎng)區(qū)間進(jìn)行比較 [step,arr.length)
            for (int i = step; i < arr.length; i++) {
                int value = arr[i];
                int j;
                //對(duì)步長(zhǎng)區(qū)間中具體的元素進(jìn)行比較
                for (j = i - step; j >= 0 && arr[j] > value; j -= step) {
                    //j為左區(qū)間的取值紊撕,j+step為右區(qū)間與左區(qū)間的對(duì)應(yīng)值赡突。
                    arr[j + step] = arr[j];
                }
                //此時(shí)step為一個(gè)負(fù)數(shù)惭缰,[j + step]為左區(qū)間上的初始交換值
                arr[j + step] = value;
            }
        }
        System.out.println(Arrays.toString(arr));
    }

三、選擇排序

1)首先在未排序序列中找到最新缭洹(大)元素昂羡,存放到排序序列的起始位置
2)再?gòu)氖S辔磁判蛟刂欣^續(xù)尋找最小(大)元素紧憾,然后放到已排序序列的末尾赴穗。
3)重復(fù)第二步,直到所有元素均排序完畢般眉。

  public static void main(String[] args) {
        int[] arr = {3,1,6,0,8};
        for (int i = 0; i < arr.length; i++) {
            // 將當(dāng)前下標(biāo)定義為最小值下標(biāo)
            int minIndex = i;
            for (int j = i+1; j <arr.length; j++) {
                if (arr[minIndex] > arr[j]) {
                    minIndex = j;
                }
            }
            //如果不是同一個(gè)甸赃,就交換
            if (i != minIndex) {
                int temp = arr[i];
                arr[i] = arr[minIndex];
                arr[minIndex] = temp;
            }
        }
        System.out.println(Arrays.toString(arr));
    }

四、冒泡排序

冒泡排序(Bubble Sort)也是一種簡(jiǎn)單直觀的排序算法络断。它重復(fù)地走訪過(guò)要排序的數(shù)列,一次比較兩個(gè)元素貌笨,如果他們的順序錯(cuò)誤就把他們交換過(guò)來(lái)锥惋。走訪數(shù)列的工作是重復(fù)地進(jìn)行直到?jīng)]有再需要交換,也就是說(shuō)該數(shù)列已經(jīng)排序完成遭商。這個(gè)算法的名字由來(lái)是因?yàn)樵叫〉脑貢?huì)經(jīng)由交換慢慢“浮”到數(shù)列的頂端捅伤。

  public static void main(String[] args) {
        int[] arr = {3,1,6,0,8};
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        System.out.println(Arrays.toString(arr));
    }

五、歸并排序

歸并排序(Merge sort)是建立在歸并操作上的一種有效的排序算法困介。該算法是采用分治法(Divide and Conquer)的一個(gè)非常典型的應(yīng)用蘸际。

    public static void main(String[] args) {
        int[] a = {3,1,6,0,8};
        int[] temp = new int[a.length];
        diao(a, 0, a.length-1,temp);
        System.out.println(Arrays.toString(a));
    }

    /**
     * 分和合 的方法
     * @param arr 原數(shù)組
     * @param left 左部分的開(kāi)始
     * @param right 右部分的結(jié)束
     * @param temp 臨時(shí)數(shù)組
     */
    public static void diao(int[] arr, int left, int right, int[] temp) {
        if (left >= right) {//如果左大于等于右 說(shuō)明到合并方法時(shí)只剩下一部分了,沒(méi)有對(duì)比 自然不能發(fā)生比較排序
            return;
        }
        int mid = (left + right) / 2;//中間索引
        diao(arr, left, mid, temp);//左遞歸分
        diao(arr, mid + 1, right, temp);//右遞歸分解
        mergeSort(arr, left, mid, right, temp);//分解完 兩部分比較 排序插入數(shù)組
    }

    /**
     * 合并方法
     * @param arr
     * @param left
     * @param mid
     * @param right
     * @param temp
     */
    public static void mergeSort(int[] arr, int left, int mid, int right, int[] temp) {

        int i = left;//記錄左部分開(kāi)頭
        int j = mid + 1;//右部分開(kāi)頭  同時(shí)也是左部分結(jié)束
        int index = 0;//輔助下標(biāo)
        while (i <= mid && j <= right) {//如果左右開(kāi)頭部分 沒(méi)到各自結(jié)尾 就繼續(xù)合并 直到一部分處理完畢
            //如果左邊小于右邊 將左邊添加到temp
            //同時(shí) index++ i++
            if (arr[i] <= arr[j]) {
                temp[index] = arr[i];
                index++;
                i++;
            } else {//反之 index++  j++
                temp[index] = arr[j];
                index++;
                j++;
            }
        }
        //當(dāng) 兩部分有一個(gè)處理完畢 剩下一個(gè) 將剩下部分的數(shù)字 全部填入temp
        while (i <= mid) {
            temp[index] = arr[i];
            index++;
            i++;
        }
        while (j <= right) {
            temp[index] = arr[j];
            index++;
            j++;
        }
        //將temp數(shù)組部分拷貝到 arr
        //注意不是 temp全部拷貝 而是沒(méi)次調(diào)用合方法中 比較的兩個(gè)部分的數(shù)字 拷貝
        //第一次合并 tempLeft = 0 , right = 1 //  tempLeft = 2  right = 3 // tL=0 ri=3
        //最后一次 tempLeft = 0  right = 7
        index = 0;
        int arrIndex=left;
        while (arrIndex <= right) {
            arr[arrIndex] = temp[index++];
            arrIndex++;
        }
    }

六、快速排序

快速排序是由東尼·霍爾所發(fā)展的一種排序算法姜骡。在平均狀況下,排序 n 個(gè)項(xiàng)目要Ο(n log n)次比較惫周。在最壞狀況下則需要Ο(n2)次比較康栈,但這種狀況并不常見(jiàn)。事實(shí)上登舞,快速排序通常明顯比其他Ο(n log n) 算法更快悬荣,因?yàn)樗膬?nèi)部循環(huán)(inner loop)可以在大部分的架構(gòu)上很有效率地被實(shí)現(xiàn)出來(lái)。

    public static void main(String[] args) {
        int[] arr = {3, 1, 6, 0, 8};
        quickSort(arr, 0, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }
    public static void quickSort(int[] arr, int low, int high) {
        int i, j, temp, t;
        if (low > high) {
            return;
        }
        i = low;
        j = high;
        //temp就是基準(zhǔn)位
        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;
            }
        }
        //最后將基準(zhǔn)為與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);
    }

七轧简、堆排序

堆排序(Heapsort)是指利用堆這種數(shù)據(jù)結(jié)構(gòu)所設(shè)計(jì)的一種排序算法匾二。堆積是一個(gè)近似完全二叉樹(shù)的結(jié)構(gòu)察藐,并同時(shí)滿足堆積的性質(zhì):即子結(jié)點(diǎn)的鍵值或索引總是小于(或者大于)它的父節(jié)點(diǎn)。

    public static void main(String[] args) {
        int[] arr = {3, 1, 6, 0, 8};
        headSort(arr);
        System.out.println(Arrays.toString(arr));
    }
    /**
     * 堆排序
     */
    public static void headSort(int[] list) {
        //構(gòu)造初始堆,從第一個(gè)非葉子節(jié)點(diǎn)開(kāi)始調(diào)整,左右孩子節(jié)點(diǎn)中較大的交換到父節(jié)點(diǎn)中
        for (int i = (list.length) / 2 - 1; i >= 0; i--) {
            headAdjust(list, list.length, i);
        }
        //排序悴务,將最大的節(jié)點(diǎn)放在堆尾譬猫,然后從根節(jié)點(diǎn)重新調(diào)整
        for (int i = list.length - 1; i >= 1; i--) {
            int temp = list[0];
            list[0] = list[i];
            list[i] = temp;
            headAdjust(list, i, 0);
        }
    }

    private static void headAdjust(int[] list, int len, int i) {
        int k = i, temp = list[i], index = 2 * k + 1;
        while (index < len) {
            if (index + 1 < len) {
                if (list[index] < list[index + 1]) {
                    index = index + 1;
                }
            }
            if (list[index] > temp) {
                list[k] = list[index];
                k = index;
                index = 2 * k + 1;
            } else {
                break;
            }
        }
        list[k] = temp;
    }

八、基數(shù)排序

基數(shù)排序是一種非比較型整數(shù)排序算法别洪,其原理是將整數(shù)按位數(shù)切割成不同的數(shù)字柳刮,然后按每個(gè)位數(shù)分別比較。由于整數(shù)也可以表達(dá)字符串(比如名字或日期)和特定格式的浮點(diǎn)數(shù)痢毒,所以基數(shù)排序也不是只能使用于整數(shù)蚕甥。

    public static void main(String[] args){
        //定義整型數(shù)組
        int[] arr = {3, 1, 6, 0, 8};
        radixSort(arr, getMaxWeishu(arr));
        //調(diào)用基數(shù)排序函數(shù)
        System.out.println(Arrays.toString(arr));
    }
    //pos=1表示個(gè)位,pos=2表示十位
    public static int getNumInPos(int num, int pos) {
        int tmp = 1;
        for (int i = 0; i < pos - 1; i++) {
            tmp *= 10;
        }
        return (num / tmp) % 10;
    }
    //求得最大位數(shù)d
    public static int getMaxWeishu(int[] a) {
        int max = a[0];
        for (int i = 0; i < a.length; i++) {
            if (a[i] > max)
                max = a[i];
        }
        int tmp = 1, d = 1;
        while (true) {
            tmp *= 10;
            if (max / tmp != 0) {
                d++;
            } else {
                break;
            }
        }
        return d;
    }
    public static void radixSort(int[] a, int d) {
        int[][] array = new int[10][a.length + 1];
        for (int i = 0; i < 10; i++) {
            array[i][0] = 0;// array[i][0]記錄第i行數(shù)據(jù)的個(gè)數(shù)
        }
        for (int pos = 1; pos <= d; pos++) {
            for (int i = 0; i < a.length; i++) {// 分配過(guò)程
                int row = getNumInPos(a[i], pos);
                int col = ++array[row][0];
                array[row][col] = a[i];
            }
            for (int row = 0, i = 0; row < 10; row++) {// 收集過(guò)程
                for (int col = 1; col <= array[row][0]; col++) {
                    a[i++] = array[row][col];
                }
                array[row][0] = 0;// 復(fù)位,下一個(gè)pos時(shí)還需使用
            }
        }
    }

總結(jié)

各種排序的穩(wěn)定性敏释,時(shí)間復(fù)雜度、空間復(fù)雜度义屏、穩(wěn)定性總結(jié)如下圖:


image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末闽铐,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子踢星,更是在濱河造成了極大的恐慌隙咸,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,273評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件藏否,死亡現(xiàn)場(chǎng)離奇詭異充包,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)基矮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門家浇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人灌具,你說(shuō)我怎么就攤上這事譬巫《桨剩” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,709評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵咕缎,是天一觀的道長(zhǎng)料扰。 經(jīng)常有香客問(wèn)我,道長(zhǎng)晒杈,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,520評(píng)論 1 296
  • 正文 為了忘掉前任撰豺,我火速辦了婚禮拼余,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘匙监。我一直安慰自己,他們只是感情好梭纹,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布致份。 她就那樣靜靜地躺著,像睡著了一般绍载。 火紅的嫁衣襯著肌膚如雪滔蝉。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,158評(píng)論 1 308
  • 那天阳谍,我揣著相機(jī)與錄音螃概,去河邊找鬼。 笑死训貌,一個(gè)胖子當(dāng)著我的面吹牛冒窍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播综液,決...
    沈念sama閱讀 40,755評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼谬莹,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼约素!你這毒婦竟也來(lái)了笆凌?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,660評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤送悔,失蹤者是張志新(化名)和其女友劉穎爪模,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體洁段,經(jīng)...
    沈念sama閱讀 46,203評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡共郭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評(píng)論 3 340
  • 正文 我和宋清朗相戀三年除嘹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片尉咕。...
    茶點(diǎn)故事閱讀 40,427評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡年缎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蜕该,到底是詐尸還是另有隱情,我是刑警寧澤蛇损,帶...
    沈念sama閱讀 36,122評(píng)論 5 349
  • 正文 年R本政府宣布坛怪,位于F島的核電站股囊,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏居灯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評(píng)論 3 333
  • 文/蒙蒙 一义锥、第九天 我趴在偏房一處隱蔽的房頂上張望岩灭。 院中可真熱鬧,春花似錦柱恤、人聲如沸找爱。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,272評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)吮播。三九已至,卻和暖如春薄料,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背誊役。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工谷市, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人鹏漆。 一個(gè)月前我還...
    沈念sama閱讀 48,808評(píng)論 3 376
  • 正文 我出身青樓创泄,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親饭聚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子搁拙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評(píng)論 2 359

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