美文网首页
算法 | Java 常见排序算法(纯代码)

算法 | Java 常见排序算法(纯代码)

作者: Java编程日记 | 来源:发表于2022-03-25 19:11 被阅读0次

    目录

    汇总
    序号

    排序算法

    平均时间

    最好情况

    最差情况

    稳定度

    额外空间

    备注

    相对时间

    1

    冒泡算法

    O(n 2 )

    O(n)

    O(n 2 )

    稳定

    O(1)

    n 越小越好

    182 ms

    2

    选择算法

    O(n 2 )

    O(n 2 )

    O(n 2 )

    不稳定

    O(1)

    n 越小越好

    53 ms

    3

    插入算法

    O(n 2 )

    O(n)

    O(n 2 )

    稳定

    O(1)

    大部分排序好时好

    16 ms

    4

    快速算法

    O(nlog 2 n)

    O(nlog 2 n)

    O(n 2 )

    不稳定

    O(nlog 2 n)

    n 大时好

    719 ms

    5

    归并算法

    O(nlog 2 n)

    O(nlog 2 n)

    O(nlog 2 n)

    稳定

    O(n)

    n 大时好

    550 ms

    6

    希尔算法

    O(nlog 2 n)

    O(n)

    O(n 2 )

    不稳定

    O(1)

    197 ms/4 ms

    7

    堆排序

    O(nlog 2 n)

    O(nlog 2 n)

    O(nlog 2 n)

    不稳定

    O(1)

    n 大时好

    3 ms

    8

    计数排序

    O(n+k)

    O(n+k)

    O(n+k)

    稳定

    O(n+k)

    k 是桶的数量

    2 ms

    9

    桶排序

    O(n+k)

    O(n)

    O(n 2 )

    稳定

    O(n+k)

    11 ms

    10

    基数排序

    O(n*k)

    O(n*k)

    O(n*k)

    稳定

    O(n+k)

    4 ms

    11

    优先队列

    不稳定

    O(n)

    9 ms

    12

    Java API

    O(1)

    4 ms

    1. 冒泡排序
      每轮循环确定最值;

    public void bubbleSort(int[] nums){
    int temp;
    boolean isSort = false; //优化,发现排序好就退出
    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;
    }
    }
    }

    1. 选择排序
      每次选出最值,再交换到边上;

    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;
    }
    }
    }

    1. 插入排序
      对循环的每个数找到属于自己的位置插入;

    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;
    }
    }

    1. 快速排序
      选一个基本值,小于它的放一边,大于它的放另一边;

    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);
    }

    1. 归并排序
      分治算法;

    //归
    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);
    }

    1. 希尔排序
      引入步长减少数字交换次数提高效率;

    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;
    }
    }
    }

    1. 堆排序
      大顶堆实现升序,每次将最大值移到堆的最后一个位置上;

    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 = 2parent +1; child < len; child = child2 +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;
    }

    1. 计数排序
      按顺序统计每个数出现次数;

    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++;
        }
    }
    

    }

    1. 桶排序
      类似计数排序,不同点在于统计的是某个区间(桶)里的数;

    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++;
        }
    }
    

    }

    1. 基数排序
      按个、十、百位依次归类排序;

    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;
    }
    

    }

    1. 使用集合或 API
      11.1 优先队列
      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);
      }

    相关文章

      网友评论

          本文标题:算法 | Java 常见排序算法(纯代码)

          本文链接:https://www.haomeiwen.com/subject/kppdjrtx.html