排序算法

排序

交换、插入、选择、归并

稳定:a在b前,a = b,排序后,a仍在b前。

不稳定:a在b前,a=b,排序后,a可能在b后。

空间复杂度

快排:O(NlogN)

归并:O(N)

其余O(1)。

时间复杂度

冒泡:O(N^2)

快排:O(Nlog(N))

简单插入:O(N^2)

希尔:O(N^s)

选择:O(N^2)

堆排:O(NlogN)

归并:O(NlogN)

交换排序

  • 冒泡 稳定——平均O(n^2),最好O(n),最坏O(n^2)
  • 快排 不稳定——平均O(NlogN),最好O(NlogN),最坏O(N^2)

冒泡排序

package com.sort;

public class BubleSort implements Sort{
    private void swap(int[] nums, int j, int i) {
        int tem = nums[j];
        nums[j] = nums[i];
        nums[i] = tem;
    }

    @Override
    public void sort(int[] nums) {
        for(int i = 0;i < nums.length;i++){
            for(int j = nums.length - 1;j > 0;j--){
                if(nums[j] < nums[j - 1]){
                    swap(nums,j,j - 1);
                }
            }
        }
    }
}

快排

package com.sort;

public class QuickSort implements Sort{


    @Override
    public void sort(int[] nums) {
        quickSort(nums, 0, nums.length - 1);
    }

    private void quickSort(int[] nums, int i, int j) {
        if (i >= j) return;
        int mid = partition(nums, i, j);
        quickSort(nums, i, mid - 1);
        quickSort(nums, mid + 1, j);
    }

    private int partition(int[] nums, int l, int h) {
        int base = nums[l];
        int i = l, j = h + 1;
        while (true) {
            while (++i < h && nums[i] < base) ;
            while (--j > l && nums[j] > base) ;
       if(i >= j) break; swap(nums, i, j); } swap(nums, j, l);
return j; } private void swap(int[] nums, int i, int j) { int tem = nums[i]; nums[i] = nums[j]; nums[j] = tem; } }

插入排序

  • 插入排序 稳定——O(N^2),最坏 O(N^2),最好O(N)
  • 希尔排序 不稳定——O(N^1.3),最坏O(N^2),最好O(N)

插入排序

package com.sort;

public class InsertSort implements Sort {


    @Override
    public void sort(int[] nums) {
        for (int i = 0; i < nums.length - 1; i++) {
            for (int j = i + 1; j > 0; j--) {
                if (nums[j] < nums[j - 1]) {
                    swap(nums,j,j - 1);
                }
            }
        }
    }

    private void swap(int[] nums, int j, int i) {
        int tem = nums[i];
        nums[i] = nums[j];
        nums[j] = tem;
    }
}

希尔排序

package com.sort;

public class ShellSort implements Sort{

    @Override
    public void sort(int[] nums) {
        int h = 1;
        while (h < nums.length / 3) {
            h = h * 3 + 1;
        }
        while (h != 0) {
            for (int i = h; i < nums.length; i += h) {
                for (int j = i; j >= h && nums[j] < nums[j - h]; j -= h) {
                    swap(nums, j, j - h);
                }
            }
            h = h / 3;
        }
    }

    private void swap(int[] nums, int j, int i) {
        int tem = nums[i];
        nums[i] = nums[j];
        nums[j] = tem;
    }
}

 选择排序

分为简单选择排序和堆排序。

简单选择排序

找到未排序数组中的最小元素,放至未排序数组的开头。不稳定。

时间复杂度:3个O(N^2),空间复杂度O(1)

public class ChooseSort extends Sort{
    @Override
    void sort(int[] nums) {
        for(int i = 0;i < nums.length;i++){
            int k = i;
            for(int j = i + 1;j < nums.length;j++){
                //不稳定 2 4453,会将第一个4与3交换,造成不稳定
                if(nums[j] < nums[k]){
                    k = j;
                }
            }
            swap(nums, i, k);
        }
    }
}

堆排序

 时间复杂度,3个O(NlogN),空间O(1)

package com.sort;

public class HeapSort extends Sort {
    @Override
    void sort(int[] nums) {
        for (int i = 0; i < nums.length; i++) {
            heapInsert(nums, i);
        }
        for(int i = nums.length - 1;i >= 0;i--){
            swap(nums, 0, i);
            heapify(nums, 0, i);
        }
    }

    private void heapify(int[] nums, int i, int j) {
        int left = 2 * i + 1;
        int right = 2 * i + 2;
        int largest = i;
        while (left < j) {
            if (nums[left] > nums[i]) {
                largest = left;
            }
            if (right < j && nums[right] > nums[largest]) {
                largest = right;
            }
            if (largest == i) break;
            swap(nums, largest, i);
            i = largest;
            left = 2 * i + 1;
            right = 2 * i + 2;

        }

    }

    private void heapInsert(int[] nums, int i) {
        int parent = 0;
        while (i != 0) {
            parent = (i - 1) / 2;
            if (nums[i] > nums[parent]) {
                swap(nums, i, parent);
                i = parent;
            } else {
                break;
            }
        }

    }

}

归并排序

二路归并排序 

时间复杂度:

package com.sort;

public class MergeSort extends Sort {
    int[] help;
    @Override
    void sort(int[] nums) {
        help = new int[nums.length];
        mergeSort(nums, 0, nums.length - 1);
    }

    private void mergeSort(int[] nums, int i, int j) {
        if (i >= j) {
            return;
        }
        int mid = (j - i) / 2 + i;
        mergeSort(nums, i, mid);
        mergeSort(nums, mid + 1, j);
        merge(nums, i, mid, j);
    }

    private void merge(int[] nums, int start, int mid, int end) {
        for (int i = start; i <= end; i++) {
            help[i] = nums[i];
        }
        int k = start, i = start, j = mid + 1;
        while (k <= end) {
            if (i > mid) {
                nums[k++] = help[j++];
            } else if (j >  end) {
                nums[k++] = help[i++];
            } else if (help[i] < help[j]) {
                nums[k++] = help[i++];
            } else {
                nums[k++] = help[j++];
            }
        }

    }

}
一回生,二回熟
原文地址:https://www.cnblogs.com/zzytxl/p/12712653.html