排序方法

来源:互联网 发布:mysql获取union条数 编辑:程序博客网 时间:2024/05/01 19:32

冒牌排序

主要思想:外层循环从1到n-1,内循环从当前外层的元素的下一个位置开始,依次和外层的元素比较,出现逆序就交换。
**特点:**stable sort(稳定性排序)、In-place sort(不占用额外的空间,只是交换元素)
最优复杂度:当输入数组就是排好序的时候,复杂度为O(n),而快速排序在这种情况下会产生O(n^2)的复杂度。
最差复杂度:当输入数组为倒序时,复杂度为O(n^2)
插入排序比较适合用于“少量元素的数组”。

public class BubbleSort {    public static void main(String[] args) {        int[] array = new int[]{2, 3, 5, 8, 9, 0, 4, 5, 1, 6, 8, 7};        sort(array);        System.out.println(Arrays.toString(array));    }    private static void sort(int[] array) {        int n = array.length;        for (int i = 0; i < n-1; i++) {            for (int j = i + 1; j < n; j++) {                if (array[j] < array[i]) {                    int temp = array[i];                    array[i] = array[j];                    array[j] = temp;                }            }        }    }}

插入排序

主要思想:
**特点:**stable sort(稳定性排序)、In-place sort(不占用额外空间)
最优复杂度:当输入数组就是排好序的时候,复杂度为O(n),而快速排序在这种情况下会产生O(n^2)的复杂度。
最差复杂度:当输入数组为倒序时,复杂度为O(n^2)
插入排序比较适合用于“少量元素的数组”。
其实插入排序的复杂度和逆序对的个数一样,当数组倒序时,逆序对的个数为n(n-1)/2,因此插入排序复杂度为O(n^2)。

public class InsertSort2 {    public static void main(String[] args) {        int[] array = new int[]{2, 3, 5, 8, 9, 0, 7, 5, 1, 6, 8, 7};        sort(array);        System.out.println(Arrays.toString(array));    }    private static void sort(int[] array) {        int n = array.length;        for (int i = 1; i < n; i++) {            int key = array[i];            int j = i -1;            while (j >= 0 && array[j]>key) {                array[j + 1] = array[j];                j--;            }            array[j+1] = key;        }    }}

选择排序

**特性:**In-place sort,unstable sort。
思想:每次找一个最小值。
**最好情况时间:**O(n^2)。
**最坏情况时间:**O(n^2)。

public class SelectSort {    public static void main(String[] args) {        int[] array = new int[]{2, 3, 5, 8, 9, 0, 7, 5, 1, 6, 8, 7};        sort(array);        System.out.println(Arrays.toString(array));    }    private static void sort(int[] array) {        int n = array.length;        for (int i = 0; i < n-1; i++) {            int min = i;            for (int j = i+1; j < n; j++) {                if (array[j] < array[min]) min = j;            }            int temp = array[i];            array[i] = array[min];            array[min] = temp;        }    }}

希尔排序

思想:基于插入排序,交换不相邻的元素已对数组的局部进行排序,并最终用插入排序将局部有序的数组排序。思想是使数组中任意间隔为h的元素都是有序的,这样的数组称为h有序数组.
**特性:**In-place sort,unstable sort。
**最好情况时间:**O(n)。
**最坏情况时间:**O(n^2)。

public class ShellSort {    public static void main(String[] args) {        int[] array = new int[]{2, 3, 5, 8, 9, 0, 7, 5, 1, 6, 8, 7, 15};        sort(array);        System.out.println(Arrays.toString(array));    }    private static void sort(int[] array) {        int n = array.length;        int h = 1;        while (h<n/3) h = 3*h +1;        while (h >= 1) {            for (int i = h; i < n; i++) {                for (int j = i; j >= h && (array[j] < array[j - h]); j -= h) {                    int temp = array[j];                    array[j] = array[j - h];                    array[j-h]= temp;                }            }            h /=3;        }    }}

归并排序

**特点:**stable sort、Out-place sort
思想:运用分治法思想解决排序问题。
**最坏情况运行时间:**O(nlgn)
**最佳运行时间:**O(nlgn)
程序中merge的精髓(也就是排序):左半边用尽,则取右半边元素;右半边用尽,则取左半边元素;右半边的当前元素小于左半边的当前元素,则取右半边元素;右半边的当前元素大于左半边的当前元素,则取左半边的元素。实际上大部分发生的都是后面两句话,前面两句只是特殊情况而已。

//自顶向下:public class MergeSort {    public static void main(String[] args) {        int[] array = new int[]{2, 3, 5, 8, 9, 0, 7, 5, 1, 6, 8, 7};        mergeSort(array);        System.out.println(Arrays.toString(array));    }    private static void mergeSort(int[] array) {        int[] aux = new int[array.length];        sort(array, aux, 0, array.length - 1);    }    private static void sort(int[] array, int[] aux, int lo, int hi) {        if (hi<=lo) return;        int mid = lo + (hi - lo)/2;        sort(array, aux, lo, mid);        sort(array, aux, mid + 1, hi);        merge(array, aux, lo, mid, hi);    }    private static void merge(int[] array, int[] aux, int lo, int mid, int hi) {        System.arraycopy(array,0,aux,0,array.length);        int i = lo, j = mid + 1;        for (int k = lo; k <= hi; k++) {            if (i>mid) array[k] = aux[j++];            else if (j > hi) array[k] = aux[i++];            else if (aux[j]<aux[i]) array[k] = aux[j++];            else array[k] = aux[i++];        }    }}
自底向上:public class MergeSort2 {    public static void main(String[] args) {        int[] array = new int[]{2, 3, 5, 8, 9, 0, 7, 5, 1, 6, 8, 7};        sort(array);        System.out.println(Arrays.toString(array));    }    public static void sort(int[] array) {        int N = a.length;        int[] aux = new int[N];        for (int n = 1; n < N; n = n+n) {            for (int i = 0; i < N-n; i += n+n) {                int lo = i;                int m  = i+n-1;                int hi = Math.min(i+n+n-1, N-1);                merge(array, aux, lo, m, hi);            }        }    }    private static void merge(int[] array, int[] aux, int lo, int mid, int hi) {        for (int k = lo; k <= hi; k++) {            aux[k] = array[k];        }        // merge back to a[]        int i = lo, j = mid+1;        for (int k = lo; k <= hi; k++) {            if      (i > mid)              array[k] = aux[j++];  // this copying is unneccessary            else if (j > hi)               array[k] = aux[i++];            else if (aux[j]<aux[i]) array[k] = aux[j++];            else                           array[k] = aux[i++];        }    }}

快速排序

**特性:**unstable sort、In-place sort。
最坏运行时间:当输入数组已排序时,时间为O(n^2),当然可以通过随机化来改进(shuffle array 或者 randomized select pivot),使得期望运行时间为O(nlgn)。
**最佳运行时间:**O(nlgn)
快速排序的思想也是分治法。
当输入数组的所有元素都一样时,不管是快速排序还是随机化快速排序的复杂度都为O(n^2),而在算法导论第三版的思考题7-2中通过改变Partition函数,从而改进复杂度为O(n)。

public class Quick3way {    public static void main(String[] args) {        int[] array = new int[]{2, 3, 5, 8, 9, 0, 7, 5, 1, 6, 8, 7};        sort(array);        System.out.println(Arrays.toString(array));    }    private static void sort(int[] array) {        shuffle(array);        sort(array, 0, array.length - 1);    }    private static void sort(int[] array, int lo, int hi) {        if (hi <= lo) return;        int lt = lo, gt = hi;        int v = array[lo];        int i = lo;        while (i <= gt) {            if      (array[i]<v) exch(array, lt++, i++);            else if (array[i]>v) exch(array, i, gt--);            else              i++;        }        // a[lo..lt-1] < v = a[lt..gt] < a[gt+1..hi].        sort(array, lo, lt-1);        sort(array, gt+1, hi);    }    private static void exch(int[] a, int i, int j) {        int swap = a[i];        a[i] = a[j];        a[j] = swap;    }    /**     *打乱数组     */    private static void shuffle(int[] array) {        Random random = new Random(System.currentTimeMillis());        if (array == null) throw new NullPointerException("argument array is null");        int n = array.length;        for (int i = 0; i < n; i++) {            int r = i + random.nextInt(n-i);     // between i and n-1            int temp = array[i];            array[i] = array[r];            array[r] = temp;        }    }}

堆排序

**特性:**unstable sort、In-place sort。
**最优时间:**O(nlgn)
**最差时间:**O(nlgn)

public class HeapSort {    public static void main(String[] args) {        int[] array = new int[]{2, 3, 5, 8, 9, 0, 7, 5, 1, 6, 8, 7};        sort(array);        System.out.println(Arrays.toString(array));    }    public static void sort(int[] a){        int N = a.length;        int[] keys = new int[N+1];        //注意,堆的数据结构是从1开始的,0不用        for (int i = 1; i < keys.length; i++) {            keys[i] = a[i-1];        }//      //构造堆,使得堆是有序的        for(int k = N/2;k>=1;k--) sink(keys,k,N);        //排序,相当于毁掉堆        while(N>1){            exch(keys,1,N--);            sink(keys,1,N);        }        //重新写回数组        for (int i = 0; i < a.length; i++) {            a[i] = keys[i+1];        }    }    private static void sink(int[] a, int k, int N) {        // TODO Auto-generated method stub        while(2*k<=N){            int j = 2*k;            if (j < N && less(a[j], a[j+1])) j++;            if (less(a[j], a[k])) break;            exch(a, k, j);            k = j;        }    }    private static boolean less(int k, int j) {        // TODO Auto-generated method stub        return k < j;    }    private static void exch(int[] a, int i, int n) {        // TODO Auto-generated method stub        int temp = a[i];        a[i] = a[n];        a[n] = temp;    }}
0 0
原创粉丝点击