算法 | Java 常見排序算法(純代碼)

匯總

序號 排序算法 平均時間 最好情況 最差情況 穩(wěn)定度 額外空間 備注 相對時間
1 冒泡算法 O(n2) O(n) O(n2) 穩(wěn)定 O(1) n 越小越好 182 ms
2 選擇算法 O(n2) O(n2) O(n2) 不穩(wěn)定 O(1) n 越小越好 53 ms
3 插入算法 O(n2) O(n) O(n2) 穩(wěn)定 O(1) 大部分排序好時好 16 ms
4 快速算法 O(nlog2n) O(nlog2n) O(n2) 不穩(wěn)定 O(nlog2n) n 大時好 719 ms
5 歸并算法 O(nlog2n) O(nlog2n) O(nlog2n) 穩(wěn)定 O(n) n 大時好 550 ms
6 希爾算法 O(nlog2n) O(n) O(n2) 不穩(wěn)定 O(1) 197 ms/4 ms
7 堆排序 O(nlog2n) O(nlog2n) O(nlog2n) 不穩(wěn)定 O(1) n 大時好 3 ms
8 計數(shù)排序 O(n+k) O(n+k) O(n+k) 穩(wěn)定 O(n+k) k 是桶的數(shù)量 2 ms
9 桶排序 O(n+k) O(n) O(n2) 穩(wěn)定 O(n+k) 11 ms
10 基數(shù)排序 O(n*k) O(n*k) O(n*k) 穩(wěn)定 O(n+k) 4 ms
11 優(yōu)先隊列 不穩(wěn)定 O(n) 9 ms
12 Java API O(1) 4 ms

1. 冒泡排序

每輪循環(huán)確定最值全肮;

public void bubbleSort(int[] nums){
    int temp;
    boolean isSort = false; //優(yōu)化秉沼,發(fā)現(xiàn)排序好就退出
    for (int i = 0; i < nums.length-1; i++) {
        for (int j = 0; j < nums.length-1-i; j++) {  //每次排序后能確定較大值
            if(nums[j] > nums[j+1]){
                isSort = true;
                temp = nums[j];
                nums[j] = nums[j+1];
                nums[j+1] = temp;
            }
        }
        if(!isSort){
            return;
        } else {
            isSort = false;
        }
    }
}


2. 選擇排序

每次選出最值桌粉,再交換到邊上行贪;

public void selectSort(int[] nums){
    for (int i = 0; i < nums.length-1; i++) {
        int index = i;
        int minNum = nums[i];
        for (int j = i+1; j < nums.length; j++) {
            if(nums[j] < minNum){
                minNum = nums[j];
                index = j;
            }
        }
        if(index != i){
            nums[index] = nums[i];
            nums[i] = minNum;
        }
    }
}


3. 插入排序

對循環(huán)的每個數(shù)找到屬于自己的位置插入丝格;

public void insertionSort(int[] nums){
    for (int i = 1; i < nums.length; i++) {
        int j = i;
        int insertNum = nums[i];
        while(j-1 >= 0 && nums[j-1] > insertNum){
            nums[j] = nums[j-1];
            j--;
        }
        nums[j] = insertNum;
    }
}


4. 快速排序

選一個基本值,小于它的放一邊恕曲,大于它的放另一邊褥影;

public void quickSortDfs(int[] nums, int left, int right){
    if(left > right){
        return;
    }
    int l = left;
    int r = right;
    int baseNum = nums[left];
    while(l < r){
        //必須右邊先走
        while(nums[r] >= baseNum && l < r){
            r--;
        }
        while(nums[l] <= baseNum && l < r){
            l++;
        }
        int temp = nums[l];
        nums[l] = nums[r];
        nums[r] = temp;
    }
    nums[left] = nums[l];
    nums[l] = baseNum;
    quickSortDfs(nums, left, r-1);
    quickSortDfs(nums, l+1, right);
}


5. 歸并排序

分治算法;

//歸
public void mergeSortDfs(int[] nums, int l, int r){
    if(l >= r){
        return;
    }
    int m = (l+r)/2;
    mergeSortDfs(nums, l, m);
    mergeSortDfs(nums, m+1, r);
    merge(nums, l, m, r);
}
//并
private void merge(int[] nums, int left, int mid, int right){
    int[] temp = new int[right-left+1];
    int l = left;
    int m = mid+1;
    int i = 0;
    while(l <= mid && m <= right){
        if(nums[l] < nums[m]){
            temp[i++] = nums[l++];
        } else {
            temp[i++] = nums[m++];
        }
    }
    while(l <= mid){
        temp[i++] = nums[l++];
    }
    while(m <= right){
        temp[i++] = nums[m++];
    }
    System.arraycopy(temp, 0, nums, left, temp.length);
}


6. 希爾排序

引入步長減少數(shù)字交換次數(shù)提高效率仑荐;

6.1 希爾-冒泡排序(慢)

public void shellBubbleSort(int[] nums){
    for (int step = nums.length/2; step > 0 ; step /= 2) {
        for (int i = step; i < nums.length; i++) {
            for (int j = i-step; j >= 0; j -= step) {
                if(nums[j] > nums[j+step]){
                    int temp = nums[j];
                    nums[j] = nums[j+step];
                    nums[j+step] = temp;
                }
            }
        }
    }
}

6.2 希爾-插入排序(快)

public void shellInsertSort(int[] nums){
    for (int step = nums.length/2; step > 0; step /= 2) {
        for (int i = step; i < nums.length; i++) {
            int j = i;
            int insertNum = nums[i];
            while(j-step >= 0 && nums[j-step] > insertNum){
                nums[j] = nums[j-step];
                j-=step;
            }
            nums[j] = insertNum;
        }
    }
}


7. 堆排序

大頂堆實現(xiàn)升序雕拼,每次將最大值移到堆的最后一個位置上;

public void heapSort2(int[] nums) {
    for(int i = nums.length/2-1; i >= 0; i--){
        sift(nums, i, nums.length);
    }
    for (int i = nums.length-1; i > 0; i--) {
        int temp = nums[0];
        nums[0] = nums[i];
        nums[i] = temp;
        sift(nums, 0, i);
    }
}
private void sift(int[] nums, int parent, int len) {
    int value = nums[parent];
    for (int child = 2*parent +1; child < len; child = child*2 +1) {
        if(child+1 < len && nums[child+1] > nums[child]){
            child++;
        }
        if(nums[child] > value){
            nums[parent] = nums[child];
            parent = child;
        } else {
            break;
        }
    }
    nums[parent] = value;
}


8. 計數(shù)排序

按順序統(tǒng)計每個數(shù)出現(xiàn)次數(shù)粘招;

public void countSort(int[] nums){
    int max = Integer.MIN_VALUE;
    int min = Integer.MAX_VALUE;
    for(int num : nums){
        max = Math.max(max, num);
        min = Math.min(min, num);
    }

    int[] countMap = new int[max-min+1];
    for(int num : nums){
        countMap[num-min]++;
    }
    int i = 0;
    int j = 0;
    while(i < nums.length && j < countMap.length){
        if(countMap[j] > 0){
            nums[i] = j+min;
            i++;
            countMap[j]--;
        } else {
            j++;
        }
    }
}


9. 桶排序

類似計數(shù)排序啥寇,不同點在于統(tǒng)計的是某個區(qū)間(桶)里的數(shù);

public void bucketSort(int[] nums){
    int max = Integer.MIN_VALUE;
    int min = Integer.MAX_VALUE;
    for(int num : nums){
        max = Math.max(max, num);
        min = Math.min(min, num);
    }
    int bucketCount = (max-min)/nums.length+1;
    List<List<Integer>> bucketList = new ArrayList<>();
    for (int i = 0; i < bucketCount; i++) {
        bucketList.add(new ArrayList<>());
    }

    for(int num : nums){
        int index = (num-min)/nums.length;
        bucketList.get(index).add(num);
    }
    for(List<Integer> bucket : bucketList){
        Collections.sort(bucket);
    }

    int j = 0;
    for(List<Integer> bucket : bucketList){
        for(int num : bucket){
            nums[j] = num;
            j++;
        }
    }
}


10. 基數(shù)排序

按個洒扎、十辑甜、百位依次歸類排序;

public  void radixSort(int[] nums){
    int min = Integer.MAX_VALUE;
    int max = Integer.MIN_VALUE;
    for (int num : nums) {
        min = Math.min(min, num);
        max = Math.max(max, num);
    }
    for (int i = 0; i < nums.length; i++) {
        nums[i] -= min;
    }
    max -= min;
    int maxLen = (max+"").length();

    int[][] bucket = new int[nums.length][10];
    int[] bucketCount = new int[10];

    for (int i = 0, n = 1; i < maxLen; i++, n*=10) {
        for (int num : nums) {
            int digitVal = num / n % 10;
            bucket[bucketCount[digitVal]][digitVal] = num;
            bucketCount[digitVal]++;
        }
        int index = 0;
        for (int j = 0; j < bucketCount.length; j++) {
            if(bucketCount[j] > 0){
                for (int k = 0; k < bucketCount[j]; k++) {
                    nums[index] = bucket[k][j];
                    index++;
                }
            }
            bucketCount[j] = 0;
        }
    }
    for (int i = 0; i < nums.length; i++) {
        nums[i] += min;
    }
}


11. 使用集合或 API

11.1 優(yōu)先隊列

public void priorityQueueSort(int[] nums){
    PriorityQueue<Integer> queue = new PriorityQueue<>();
    for(int num : nums){
        queue.offer(num);
    }
    for (int i = 0; i < nums.length; i++) {
        nums[i] = queue.poll();
    }
}

11.2 Java API

public void arraysApiSort(int[] nums){
    Arrays.sort(nums);
}



最后

\color{blue}{\rm\small{新人制作袍冷,如有錯誤磷醋,歡迎指出,感激不盡胡诗!}}

\color{blue}{\rm\small{歡迎關(guān)注我邓线,并與我交流!}}

\color{blue}{\rm\small{如需轉(zhuǎn)載煌恢,請標注出處骇陈!}}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市瑰抵,隨后出現(xiàn)的幾起案子你雌,更是在濱河造成了極大的恐慌,老刑警劉巖二汛,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件婿崭,死亡現(xiàn)場離奇詭異,居然都是意外死亡肴颊,警方通過查閱死者的電腦和手機氓栈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來婿着,“玉大人颤绕,你說我怎么就攤上這事幸海。” “怎么了奥务?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵物独,是天一觀的道長。 經(jīng)常有香客問我氯葬,道長挡篓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任帚称,我火速辦了婚禮官研,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘闯睹。我一直安慰自己戏羽,他們只是感情好,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布楼吃。 她就那樣靜靜地躺著始花,像睡著了一般。 火紅的嫁衣襯著肌膚如雪孩锡。 梳的紋絲不亂的頭發(fā)上酷宵,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機與錄音躬窜,去河邊找鬼浇垦。 笑死,一個胖子當著我的面吹牛荣挨,可吹牛的內(nèi)容都是我干的男韧。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼默垄,長吁一口氣:“原來是場噩夢啊……” “哼此虑!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起厕倍,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤寡壮,失蹤者是張志新(化名)和其女友劉穎贩疙,沒想到半個月后讹弯,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡这溅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年组民,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片悲靴。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡臭胜,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情耸三,我是刑警寧澤乱陡,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站仪壮,受9級特大地震影響憨颠,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜积锅,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一爽彤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧缚陷,春花似錦适篙、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蝶缀,卻和暖如春丹喻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背翁都。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工碍论, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人柄慰。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓鳍悠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親坐搔。 傳聞我的和親對象是個殘疾皇子藏研,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

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