几种基本的排序算法

本文将介绍几种基本的排序算法,如冒泡排序,选择排序,插入排序,希尔排序,归并排序。

首先写好交换两个元素的模板:

private void exch(int[] a, int lo, int hi) {
        int temp = a[lo];
        a[lo] = a[hi];
        a[hi] = temp;
    }

冒泡排序:

冒泡排序是最简单的排序方法,即将元素两两之间相比较,然后进行排序,算法的代码如下;

public void sort(int[] a) {
        for (int i = 0; i < a.length - 1; i++) {
            for (int j = i + 1; j < a.length; j++) {
                if (a[i] > a[j]) {
                    exch(a, i, j);
                }
            }
        }
    }

但是此种冒泡排序有种缺陷,即两两排序的时候可能会将相对比较小的值换到后面,这样的话又增加了交换的次数,如果是从后面开始往前进行比较的话就不会存在这种情况,同时,在从后往前进行两两比较的时候,如果在某次进行两两相比较之时已经处于有序状态,那么即可以退出循环,不再比较。

改进代码:

public void sort(int[] a) {
        boolean flag = true;                                      //flag判断是否进行了交换
        for (int i = 0; i < a.length - 1 && flag == true; i++) {  //若未进行交换,则退出循环
            flag = false;
            for (int j = a.length - 2; j >= i; j--) {
                if (a[j] > a[j + 1]) {
                    exch(a, j, j + 1);
                    flag = true;
                }
            }
        }
    }

选择排序:

顾名思义,选择排序,即先选择好序列中的最小元素,然后交换之。换言之,也就是比较的次数并没有发生多少,但是只交换一次,比冒泡排序稍好一些。

    /**
     * 定义一个下标min,若值比a[min]小,则令min为相应的下标值,再将a[min]与a[i]交换即可
     * @param a
     */
    public void sort(int[] a) {
        for (int i = 0; i < a.length - 1; i++) {  
            int min = i;
            for (int j = i + 1;j < a.length; j--) {
                if (a[min] > a[j]) {
                    min = j;
                }
            }
            if(min != i){
                exch(a, i, min);
            }
        }
    }

插入排序:

插入排序就像是扑克牌抓牌一样,当抓到一张较小的牌的时候,需要将它插到比它大的(两者之间的差最小的)牌的左边,并且将牌相应的向右移动。代码如下:

public void sort(int[] a) {
            for(int i = 1; i < a.length; i++){
                   for(int j = i; j > 0 && (a[j] < a[j - 1]); j--){
                       exch(a, j, j - 1);
                }
            }
        }

希尔排序:

第一个将时间复杂度突破到O(n*n)之下的。依然是使用的插入排序,也就是在插入排序的基础之上选定一段距离进行插入排序。

public void sort(int[] a) {
            int h = 1;
            while(h < a.length / 3){
                h = 3 * h + 1;
            }
            while(h >= 1) {
                for (int i = h; i < a.length; i++) {
                    for (int j = i; j >= h && (a[j] < a[j - h]); j -= h) {
                        exch(a, j, j - h);
                    }
                }
                h = h / 3;
            }
        }

归并排序:

将一个序列分成两段,分别进行排序,然后再整体排序。

        private static int[] temp;
        public void sort(int[] a) {
            temp = new int[a.length];
            sort(a, 0, a.length - 1);
        }
        private void sort(int[] a, int lo, int hi){

            if(lo >= hi){return;}
            int mid = (lo + hi) / 2;
            sort(a, lo, mid);
            sort(a,mid + 1, hi);
            merge(a, lo, mid, hi);
        }
        private void merge(int[] a, int lo, int mid, int hi){
            for(int i = lo; i <= hi; i++){
                temp[i] = a[i];
            }
            int i = lo;
            int j = mid + 1;
            for(int k = lo; k <= hi; k++) {
                if(i > mid){a[k] = temp[j++];}
                else if(j > hi){a[k] = temp[i++];}
                else if(temp[i] > temp[j]){
                    a[k] = temp[j++];
                }else{
                    a[k] = temp[i++];
                }
            }
        }
点赞