排序算法

我们通常所说的排序算法往往指的是内部排序算法,即数据记录在内存中进行排序。排序算法大体可分为两种:一种是比较排序,时间复杂度O(nlogn) ~ O(n^2),主要有:冒泡排序选择排序插入排序归并排序堆排序快速排序等。另一种是非比较排序,时间复杂度可以达到O(n),主要有:计数排序基数排序桶排序等。

 算法复杂度

 冒泡排序

一组无序的数据arr[0]、arr[1]、……arr[n],按升序排列,首先比较a[0]与a[1]的值,若a[0]大于a[1]则交换两者的值,否则不变。再比较a[1]与a[2]的值,若a[1]大于a[2]则交换两者的值,否则不变。再比较a[2]与a[3],以此类推,最后比较a[n-1]与a[n]的值。这样处理一轮后,a[n]的值一定是这组数据中最大的。用相同的方法对a[0]~a[n-1]以相同处理一轮,则a[n-1]的值一定是a[0]~a[n-1]中最大的。以此循环,最后比较a[0]和a[1]位置的两个值,若a[0]大于a[1]则交换位置,否则不变。理论上总共要进行n(n-1)/2次交换。代码实现如下:

 public static void bubbleSort(int[] arr) {
        for (int i = 1; i < arr.length; i++) {
            for (int j = 0; j < arr.length - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }

选择排序

选择排序的工作原理:初始时在序列中找到最小(大)元素,放到序列的起始位置作为已排序序列;然后,再从剩余未排序元素中继续寻找最小(大)元素,放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。代码实现如下:

    public static void selectSort(int[] arr) {
        for(int i = 0; i < arr.length; i++) {
            int k = i;
            for(int j = arr.length-1; j > i; j --) {
                if(arr[j] < arr[k]) {
                    k = j;
                }
            }
            int temp = arr[i];
            arr[i] = arr[k];
            arr[k] = temp;
        }
        System.out.println(Arrays.toString(arr));
    }

插入排序

插入排序的工作原理:每步将一个待排序的记录,按其顺序码大小插入到前面已经排序的字序列的合适位置(从后向前找到合适位置后),直到全部插入排序完为止。

    public static void inserSort (int[] arr) {
        int j = 0;
        for(int i = 0; i < arr.length; i ++) {
            int temp = arr[i];
            for( j = i; j> 0 && temp < arr[j-1];j--) {
                arr[j] = arr[j-1];
            }
            arr[j] = temp;
        }
    }

归并排序

归并排序的工作原理:通过将数组不断地二分,直到最后每个部分只包含 1 个数据。然后再对每个部分分别进行排序,最后将排序好的相邻的两部分合并在一起,这样整个数组就有序了。

 public static void customMergeSort(int[] a, int[] tmp, int start,int end){
        if(start < end) {
            int mid = (start+end)/2;
            customMergeSort(a,tmp,start,mid);
            customMergeSort(a,tmp,mid+1,end);
            customDoubleMerge(a,tmp,start,mid,end);
        }
     }

    public static void  customDoubleMerge(int[] a, int[] tmp, int left,int mid,int right){
        int p1 = left, p2= mid+1, k = left;
        while(p1 <= mid && p2 <= right) {
            if (a[p1] <= a[p2]) {
                tmp[k++] = a[p1++];
            } else {
                tmp[k++] = a[p2++];
            }
        }
        while(p1 <= mid){
            tmp[k++] = a[p1++];
        }
        while(p2 <= right){
            tmp[k++] = a[p2++];
        }
        for(int i = left; i <= right; i++) {
            a[i] = tmp[i];
        }
    }

快速排序

快速排序的工作原理:通过一趟排序将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分关键字小,则分别对这两部分继续进行排序,直到整个序列有序。

    public static int partition(int[] a, int low, int high) {
        int pivotkey = a[low];  //数组的第一个作为中轴
        while (low < high) {
            while (low < high && a[high] >= pivotkey)
                --high;
            a[low] = a[high];    //比中轴小的记录移到低端
            while (low < high && a[low] <= pivotkey)
                ++low;
            a[high] = a[low];   //比中轴大的记录移到高端
        }
        a[low] = pivotkey;  //中轴记录到尾
        return low;     // 返回中轴的位置
    }

    /**
     * @param arr 带排序数组
     * @param low     开始位置
     * @param high    结束位置
     */
    public static void quickSort(int[] arr, int low, int high) {
        if (low < high) {
            int middle = partition(arr, low, high); //将arr数组进行一分为二
            quickSort(arr, low, middle - 1);   //对低字段表进行递归排序
            quickSort(arr, middle + 1, high); //对高字段表进行递归排序
        }

    }

 

posted @ 2018-11-16 23:20  loytime  阅读(215)  评论(0编辑  收藏  举报