java 实现所有的排序算法


所有算法代码下载可以访问此GitHub地址:https://github.com/pu2014/myAlgorithm

java 所有排序算法

java 常用的排序有Collections.sort 和 Arrays.sort的排序方法其中Collections.sort()对集合实现排序,其源码为:

@SuppressWarnings({"unchecked", "rawtypes"})
  default void sort(Comparator<? super E> c) {
      Object[] a = this.toArray();
      Arrays.sort(a, (Comparator) c);
      ListIterator<E> i = this.listIterator();
      for (Object e : a) {
          i.next();
          i.set((E) e);
      }
  }

        可以看出是内部是利用Arrays.sort()将集合转化的数组实现排序。Arrays.sort使用了两种排序方法,快速排序和优化的归并排序。快速排序主要是对那些基本类型数据(int,short,long等)排序, 而归并排序用于对Object类型进行排序。

排序原则

  1. 若你需要排序的是基本数据类型,则选择快速排序。若你需要排序的是引用数据类型,则选择归并排序。(基于稳定性考虑)因为基本数据类型之间无差异,不需要考虑排序算法稳定性,而归并排序则可以实现算法的稳定性。
  2. 当你需要排序的样本数量小于60,直接选择插入排序,虽然插入排序的时间复杂度为O(N²),我们是忽略常数项得出来的O(N²),但在魔数60以内,插入排序的时间复杂度为O(N²)的劣势体现不出来,反而插入排序常数项很低,导致在小样本情况下,插入排序极快。 如果一开始数组容量很大,但可以分治处理分
    治后如果数组容量(L>R - 60)小于60,可以直接选择插排。当大样本下考虑情况1。
插入排序 N^2
private static void insertSort(int[] arr) {
        if(arr.length < 2 || arr == null)
            return;
        for (int i = 1; i < arr.length; i++) {  // 0 - (i- 1)已排好序,将新来元素arr[i]插入到已排好序的数组中
            for (int j = i - 1; j >= 0; j--) {
                if(arr[j] > arr[j + 1]){   
                    swap(arr,j,j+1);
                }
            }
        }
    }
快速排序 NlogN
private static void quickSort(int[] arr) {
        quickSorting(arr,0,arr.length - 1);

    }

    private static void quickSorting(int[] arr, int left, int right) {
        if(left < right) {
            int[] index = partition(arr, left, right);
            quickSorting(arr, left, index[0] - 1);
            quickSorting(arr, index[1] + 1, right);
        }
    }

    private static int[] partition(int[] arr, int left, int right) {
        //随机选取,经典排序
        int pivot = arr[(int)Math.random()*(right - left + 1) + left]; // 随机选取基准值 做partition
        int i = left;
        while(i <= right){
            if(arr[i] < pivot){
                swap(arr,i++,left++);
            }else if(arr[i] > pivot){
                swap(arr,i,right--);
            }else {
                i++;
            }
        }
        return new int[]{left,right};
    }
归并排序 NlogN
private static void mergeSort(int[] arr,int L,int R) {
        if (L == R)
            return;
        int mid = L + ((R - L) >> 1);
        mergeSort(arr,L,mid);
        mergeSort(arr,mid + 1,R);
        merge(arr,L,mid,R);
    }

    private static void merge(int[] arr, int L, int mid, int R) {
        int[] ex = new int[R - L + 1];
        int i = 0; //ex数组的坐标
        int p = L;
        int q = mid + 1;
        while(p <= mid && q <= R){
            ex[i++] = arr[p] < arr[q] ? arr[p++]:arr[q++];
        }
        while(p <= mid){
            ex[i++] = arr[p++];
        }
        while (q <= R){
            ex[i++] = arr[q++];
        }
        for (int j = 0; j < ex.length; j++) {
            arr[L + j] = ex[j];
        }
    }
选择排序和冒泡排序 N^2
private static void selectSort(int[] arr) {
        if(arr == null || arr.length < 2)
            return;
        for (int i = 0; i < arr.length; i++) {
            for (int j = i; j < arr.length; j++) {
                if(arr[j] < arr[i]){
                    swap(arr,i,j);
                }
            }
        }
    }


private static void bubbleSort(int[] arr) {
        if(arr.length < 2 || arr == null){
            return;
        }
        int temp = 0;
        for (int i = arr.length -1 ; i >= 0; i--) {
            for (int j = 0; j < i ; j++) {
                if(arr[j] > arr[j + 1]){
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }
桶排序 O(M + N)

        先找出要排序的数的最大最小值。设置桶的容量。依次放入桶中。排序后按顺序出桶。

public class 排序_桶排序 {
    public static void main(String[] args){
        int[] arr = createArr(10);
        bucketSort(arr);
        System.out.println(Arrays.toString(arr));
    }

    private static void bucketSort(int[] arr) {
        int min = getArrMin(arr);
        int max = getArrMax(arr);
        int len = (max -min)/10 + 1;
        ArrayList<LinkedList<Integer>> bucket = new ArrayList<>(len);
        for(int i = 0; i < len; i++){
            bucket.add(new LinkedList<Integer>());
        }
        enterBucket(arr,bucket,min,len);
        for(LinkedList<Integer> ll:bucket){
            Collections.sort(ll);
        }
        outBucket(arr,bucket);

    }

    private static void outBucket(int[] arr, ArrayList<LinkedList<Integer>> bucket) {
        int index = 0;
        for(LinkedList<Integer> ll:bucket){
            for(Integer i : ll){
                arr[index++] = i;
            }
        }
    }

    private static void enterBucket(int[] arr, ArrayList<LinkedList<Integer>> bucket,int min,int len) {
        for(int i = 0; i < arr.length; i++){
            bucket.get((arr[i] - min) / 10).add(arr[i]);
        }
    }

    private static int getArrMax(int[] arr) {
        int max = Integer.MIN_VALUE;
        for(int i = 0;i < arr.length;i++){
            max = Math.max(max,arr[i]);
        }
        return max;
    }

    private static int getArrMin(int[] arr) {
        int min = Integer.MAX_VALUE;
        for(int i = 0;i <arr.length;i++){
            min = Math.min(min,arr[i]);
        }
        return min;
    }

    private static int[] createArr(int n) {
        int[] arr = new int[n];
        for(int i = 0;i < n;i++){
            arr[i] = (int)(Math.random() * 100);  // 0.0-0.99 包括0
        }
        System.out.println(Arrays.toString(arr));
        return arr;
    }
}
计数排序 o(n + k)

        类似桶排序,稳定

public class 排序_计数排序 {
    public static void main(String[] args) {
        int[] arr = createArr(10);
        bucketSort(arr);
        System.out.println(Arrays.toString(arr));
    }

    private static void bucketSort(int[] arr) {
        if(arr == null || arr.length < 2){
            return;
        }
        int max = Integer.MIN_VALUE;
        int min = Integer.MAX_VALUE;
        for (int i = 0; i < arr.length; i++) {
            max = Math.max(max,arr[i]);
            min = Math.min(min,arr[i]);
        }
        int[] bucket = new int[max - min + 1];
        for (int i = 0; i < arr.length; i++) {
            bucket[arr[i] - min]++;
        }
        int i = 0;
        for (int j = 0; j < bucket.length; j++) {
            while (bucket[j]-- > 0){
                arr[i++] = j;
            }
        }
    }

    private static int[] createArr(int n) {
        int[] arr = new int[n];
        for(int i = 0;i < n;i++){
            arr[i] = (int)(Math.random() * 100);  // 0.0-0.99 包括0
        }
        System.out.println(Arrays.toString(arr));
        return arr;
    }
}
堆排序 O(NlogN)

        堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。
        思路
大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2] 小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]
        序列的最大值就是堆顶的根节点。 将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了

public class 排序_堆排序 {
    public static void main(String[] args) {
        int[] arr = new int[10];
        int[] arr2 = new int[10];
        for(int i = 0;i < 10;i++){
            arr[i] = (int)(Math.random() * 100);  // 0.0-0.99 包括0
        }
        for(int i = 0;i < 10;i++){
            arr2[i] = (int)(Math.random() * 100);  // 0.0-0.99 包括0
        }
        System.out.println(Arrays.toString(arr));
        heapSort(arr);
        System.out.println(Arrays.toString(arr));
        System.out.println(Arrays.toString(arr2));
        heapSort2(arr2);
        System.out.println(Arrays.toString(arr2));
    }

    private static void heapSort2(int[] arr) {
        if(arr == null || arr.length < 2){
            return;
        }
        int heapSize = arr.length; //设置堆的大小
        while (heapSize > 0){
            for (int i = 0;i < heapSize;i++){
                heapInsert(arr,i); 	//进入堆
            }
            swap(arr,0,--heapSize); //调整
        }
    }


    private static void heapSort(int[] arr) {
        if(arr == null || arr.length < 2){
            return;
        }
        for (int i = 0; i < arr.length; i++) {
            heapInsert(arr,i);
        }
        int heapSize = arr.length;
        swap(arr,0,--heapSize);
        while (heapSize > 0){
            heapify(arr,0,heapSize);
            swap(arr,0,--heapSize);
        }

    }

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

    private static void heapInsert(int[] arr, int i) {
        while (i > 0 && arr[i] > arr[(i - 1) >> 1]) {
            swap(arr, i, (i - 1) >> 1);
            i = (i - 1) >> 1;
        }
    }
    private static void swap(int arr[],int i,int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值