排序汇总 java实现

排序汇总 java实现

排序

比较

排序算法 平均时间复杂度 最差时间复杂度 空间复杂度 数据对象稳定性
冒泡排序 O(n2) O(n2) O(1) 稳定
选择排序 O(n2) O(n2) O(1) 数组不稳定、链表稳定
插入排序 O(n2) O(n2) O(1) 稳定
快速排序 O(n*log2n) O(n2) O(log2n) 不稳定
堆排序 O(n*log2n) O(n*log2n) O(1) 不稳定
归并排序 O(n*log2n) O(n*log2n) O(n) 稳定
希尔排序 O(n*log2n) O(n2) O(1) 不稳定
计数排序 O(n+m) O(n+m) O(n+m) 稳定
桶排序 O(n) O(n) O(m) 稳定
基数排序 O(k*n) O(n2) 稳定

冒泡排序

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

选择排序

注意: 第二层循环用来找最小值索引

public void sort(int[] nums){
    int n = nums.length;
    if(n == 0) return;
    for(int i = 0; i < n; i++){
        int min = i;
        for(int j = i; j < n; j++){
            if(nums[j] < nums[min])
                min = j;
        }
        swap(nums, i, min);
    }
}
private void swap(int[] nums, int i, int j){
    int tmp = nums[i];
    nums[i] = nums[j];
    nums[j] = tmp;
}

插入排序

细节:第二次循环是 j--

public void sort(int[] nums){
    int n = nums.length;
    if(n == 0) return ;
    for (int i = 1; i < n; i++) {
        for (int j = i; j > 0 && nums[j] < nums[j-1]; j--) {
            swap(nums, j, j-1);
        }
    }
}
private void swap(int[] nums , int i, int j){
    int tmp = nums[i];
    nums[i] = nums[j];
    nums[j] = tmp;
}

快速排序

细节:在partition函数中,里面的while必须要有,先判断 i 和 j 是否越界,最后出口,搞一个已经拍好序的数组来思考下

public void sort(int[] nums){
    int n = nums.length;
    if(n == 0) return;
    quickSort(nums, 0, n-1);
}
private void quickSort(int[] nums, int lo, int hi){
    if(lo >= hi) return;
    int mid = patition(nums, lo, hi);
    quickSort(nums, lo, mid-1);
    quickSort(nums, mid+1, hi);
}
private int patition(int[] nums, int lo, int hi){
    int i = lo;
    int j = hi+1;
    while (i < j){
        while (++i <= hi && nums[i] < nums[lo]);
        while (--j >= lo && nums[j] > nums[lo]);
        if(i < j)
            swap(nums, i, j);
    }
    swap(nums, lo, j);
    return j;
}
private void swap(int[] nums, int i, int j){
    int tmp = nums[i];
    nums[i] = nums[j];
    nums[j] = tmp;
}

堆排序

先建立堆,堆从一半位置开始建立就可以了
细节点:开始的n是长度-1;在下沉时如果比两边都大,就退出了

public void sort(int[] nums){
    int n = nums.length-1;
    //建堆
    for (int k = (n-1)/2; k >= 0; k--) {
        sink(nums, k, n);
    }
    //排序
    while (n > 0){
        swap(nums, 0, n--);
        sink(nums, 0, n);
    }
}
private void sink(int[] nums, int k, int n){
    while (2*k + 1 <= n){
        int j = 2*k+1;
        if(j < n && nums[j] < nums[j+1]) j++;
        if(nums[j] < nums[k]) break;
        swap(nums, j, k);
        k = j;
    }
}
private void swap(int[] nums, int i, int j){
    int tmp = nums[i];
    nums[i] = nums[j];
    nums[j] = tmp;
}

归并排序

细节:注意merge时判断大小是用aux,否则会出错

public void sort(int[] nums){
    int n = nums.length;
    if(n == 0) return;
    aux = new int[n];
    mergeSort(nums, 0 , n-1);
}
int[] aux;
private void mergeSort(int[] nums, int lo ,int hi){
    if(lo >= hi) return;
    int mid = lo + (hi - lo)/2;
    mergeSort(nums, lo, mid);
    mergeSort(nums,mid+1,hi);
    if(nums[mid] >nums[mid+1])
        merge(nums, lo, mid, hi);
}
private void merge(int[] nums, int lo, int mid, int hi){
    for(int k = lo; k <= hi; k++)
        aux[k] = nums[k];
    int i = lo;
    int j = mid+1;
    for (int k = lo; k <= hi; k++) {
        if(i > mid) nums[k] = aux[j++];
        else if(j > hi) nums[k] = aux[i++];
        else if(aux[i] > aux[j]){
            nums[k] = aux[j++];
        }else{
            nums[k] = aux[i++];
        }
    }
}

希尔排序

注意:先得到h为多少,然后第一层循环从h开始,第二层循环判断条件时 >= h; 且都是 - h

public void sort(int[] nums){
    int n = nums.length;
    int h = 1;
    while (h < n/3) h = h*3+1;
    while (h >= 1){
        for (int i = h; i < n; i++) {
            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 i, int j){
    int tmp = nums[i];
    nums[i] = nums[j];
    nums[j] = tmp;
}

计数排序

记录一个最小最大值,从而减少桶的数量

private void sort(int[] nums){
    int n = nums.length;
    if(n == 0) return;
    int min = nums[0];
    int max = nums[0];
    for(int num : nums){
        min = Math.min(min, num);
        max = Math.max(max, num);
    }
    int[] bucket = new int[max-min+1];
    for (int i = 0; i < nums.length; i++) {
        bucket[nums[i]-min]++;
    }
    int idx = 0;
    for (int i = min; i <= max; i++) {
        for (int j = 0; j < bucket[i]; j++) {
            nums[idx++] = i;
        }
    }
}

桶排序

range多大,就需要多大的桶

private void sort(int[] nums, int range){
    int[] bucket = new int[range];
    for (int i = 0; i < nums.length; i++) {
        bucket[nums[i]]++;
    }
    int idx = 0;
    for (int i = 0; i < range; i++) {
        for (int j = 0; j < bucket[i]; j++) {
            nums[idx++] = i;
        }
    }
}

基数排序

public void sort(int[] nums){
    int n = nums.length;
    if(n == 0) return;
    int[] aux = new int[n];
    int max = nums[0];
    for(int num : nums)
        max = Math.max(max, num);
    for(int base = 1; max / base > 0; base*=10){
        int[] count = new int[11]; //这里写为11很关键
        //统计频率
        for (int i = 0; i < n; i++)
            count[(nums[i] / base) % 10 + 1]++; //这里从1开始很关键
        //将频率转换为索引
        for(int i = 1; i < count.length; i++)
            count[i] += count[i-1];
        //将元素分类
        for(int i = 0; i < n; i++)
            aux[count[(nums[i] / base) % 10]++] = nums[i]; //这里++很关键
        //回写
        for(int i = 0; i < n; i++)
            nums[i] = aux[i];
    }
}
上一篇:Java排序遇到的坑(转)


下一篇:Java和SAP ABAP的异常处理