O(NlogN)的排序方法

归并排序

  • 采用分治的思想,将数组进行等分,将分成的两个数组分别进行排序,merge两个数组
  • 时间复杂度:O(nlogn)
  • 空间复杂度:O(logn)
  • 稳定性:稳定
package Sort;

public class MergeSort {
    public static void swap(int[] vec, int i, int j){
        int tmp = vec[i];
        vec[i] = vec[j];
        vec[j] = tmp;
    }

    public static void mergeSort(int[] vec){
        if(vec.length < 2)
            return;
        mergeSort(vec, 0, vec.length-1);
    }

    public static void mergeSort(int[] vec, int l, int r){
        if(l == r)
            return;
        int m = l + ((r - l) >> 1);
        mergeSort(vec, l, m);
        mergeSort(vec, m+1, r);
        merge(vec, l, m, r);
    }

    public static void merge(int[] vec, int l, int m, int r){
        int[] help = new int[r - l + 1];
        int i = 0;
        int p1 = l;
        int p2 = m+1;
        while(p1 <= m && p2 <= r){
            help[i++] = vec[p1] < vec[p2] ? vec[p1++] : vec[p2++];
        }

        while(p1 <= m){
            help[i++] = vec[p1++];
        }

        while(p2 <= r){
            help[i++] = vec[p2++];
        }

        for(i = 0; i < help.length; i++){
            vec[l + i] = help[i];
        }
    }

    public static void main(String[] args) {
        int[] vec = {5,2,0,7,-3,8,12};
        mergeSort(vec);
        for(int x : vec){
            System.out.print(x + "\t");
        }
    }
}

堆排序

  • 基本思想:建立一个大顶堆,每次将堆顶与末尾元素进行交换,对堆顶元素做一个heapify
  • 时间复杂度:O(nlogn)
  • 空间复杂度:O(1)
  • 稳定行:不稳定
package Sort;

public class HeapSort {
    public static void swap(int[] vec, int i, int j){
        int tmp = vec[i];
        vec[i] = vec[j];
        vec[j] = tmp;
    }

    public static void heapSort(int[] vec){
        if(vec.length < 2)
            return;
        int size = vec.length;

        for(int i = size/2; i >= 0; i--){
            heapify(vec, i, size);
        }
        swap(vec, 0, --size);

        while(size > 0){
            heapify(vec, 0, size);
            swap(vec, 0, --size);
        }
    }

    public static void heapify(int[] vec, int index, int size){
        int left = 2 * index + 1;
        while(left < size){
            int largest = left + 1 < size && vec[left] < vec[left + 1] ? left + 1 : left;
            largest = vec[largest] > vec[index] ? largest : index;
            if(largest == index)
                break;
            swap(vec, largest, index);
            index = largest;
            left = 2 * index + 1;
        }
    }

    public static void main(String[] args) {
        int[] vec = {5,2,0,7,-3,8,12};
        heapSort(vec);
        for(int x : vec){
            System.out.print(x + "\t");
        }
    }
}

快速排序

  • 采用分治的思想,随机选取数组中的一个数,以它为基准进行partition,分成左(小于基准数)中(等于基准数)右(大于基准数),对左,右重复进行该操作
  • 时间复杂度:O(nlogn)
  • 空间复杂度:O(logn)
  • 稳定性:不稳定
package Sort;

public class QuickSort {
    public static void swap(int[] vec, int i, int j){
        int tmp = vec[i];
        vec[i] = vec[j];
        vec[j] = tmp;
    }

    public static void quickSort(int[] vec){
        if(vec.length < 2)
            return;
        quickSort(vec, 0, vec.length - 1);
    }

    public static void quickSort(int[] vec, int l, int r){
        if(l < r){
            int m = l + (int)(Math.random() * (r - l + 1));
            swap(vec, m, r);
            int[] p = partition(vec, l, r);
            quickSort(vec, l, p[0] - 1);
            quickSort(vec, p[1] + 1, r);
        }
    }

    public static int[] partition(int[] vec, int l, int r){
        int less = l - 1;
        int more = r;
        while(l < more){
            if(vec[l] < vec[r]){
                swap(vec, l++, ++less);
            }
            else if(vec[l] > vec[r]){
                swap(vec, l, --more);
            }
            else{
                l++;
            }
        }
        swap(vec, more, r);
        return new int[]{less+1, more};
    }

    public static void main(String[] args) {
        int[] vec = {5,2,0,7,-3,8,12};
        quickSort(vec);
        for(int x : vec){
            System.out.print(x + "\t");
        }
    }
}
posted @ 2020-10-17 20:43  提笔书几行  阅读(328)  评论(0编辑  收藏  举报