常用排序算法使用

常用排序算法有:

1、选择排序(直接选择排序、堆排序)

2、交换排序(冒泡排序、快速排序)

3、插入排序(直接插入排序、二分插入排序、Shell排序)

4、归并排序

5、桶式排序

6、基数排序

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

1、直接选择排序

(1)、首先将第一个与第二个进行比较,如果第二个比第一个小,交换二者的位置,然后第二个与第三个进行比较…………第一趟找出最小的数据放在第一位置

(2)、第二趟从第二个开始,找出第二小的数据放在第二的位置

………………

经过N-1次排序之后就实现从小到大的排序,核心代码就是一个双重循环

package example;

import java.util.Arrays;
import java.util.Random;

public class Test {

    public static void main(String[] args) {
        Random rd = new Random();
        int[] arrays = new int[10];
        for (int i = 0; i < arrays.length; i++) {
            arrays[i] = rd.nextInt(100);
        }
        System.out.println("排序前:" + Arrays.toString(arrays));
        Sort(arrays);
        System.out.println("排序后:" + Arrays.toString(arrays));

    }

    private static void Sort(int[] arrays) {
        int temp;
        for (int i = 0; i < arrays.length - 1; i++) {
            for (int j = i + 1; j < arrays.length; j++) {
                if (arrays[i] > arrays[j]) {
                    temp = arrays[i];
                    arrays[i] = arrays[j];
                    arrays[j] = temp;
                }
            }
        }
    }
}
run:
排序前:[67, 62, 79, 29, 1, 46, 66, 50, 34, 93]
排序后:[1, 29, 34, 46, 50, 62, 66, 67, 79, 93]
成功构建 (总时间: 0 秒)


在排序中发现一个问题,由于每一次外部循环,只需要寻找最小的那个数据,然后放到开始位置去,

然后程序只要已发现前面数据比后面大,马上就会交换它们的未知,这里就增加了其开销

下面改进一下,在内部循环的时候,寻找当次外循环的最小值的位置,把这个位置记录下来,与它进行比较,然后再来交换

 private static void Sort(int[] arrays) {
        int temp;
        int index;
        for (int i = 0; i < arrays.length - 1; i++) {
            index = i;
            for (int j = i + 1; j < arrays.length; j++) {
                if (arrays[index] > arrays[j]) {
                    index = j;
                }
            }
            if (index != i) {
                temp = arrays[i];
                arrays[i] = arrays[index];
                arrays[index] = temp;
            }
        }
    }

对于直接选择排序假设有N项数据,数据交换次数最多有N-1次,程序比较次数较多,时间效率为O(N*N);但是其空间利用率高,只需要一个额外变量用于交换,空间效率O(1);直接选择排序是不稳定的。

2、堆排序

针对N个数据为:K0,K1,K2………………Kn,如果满足以下关系

Ki<=k2i+1 并且Ki<=K2i+2  (i=0,1,2…………)

则称其为小顶堆(小根堆)

反之:

Ki>=k2i+1 并且Ki>=K2i+2  (i=0,1,2…………)

则称其为大顶堆(大根堆)

步骤:

1、第一趟将索引0——N-1的数据建立大顶堆(小顶堆),就可以选出最大(最小)的数据放到根节点(索引0位置),然后将未知0与N-1位置的数据兑换,

那么最大(最小)的数据就跑到最后去了

2、第二趟将索引0——N-2的数据建立大顶堆(小顶堆),就可以选出最大(最小)的数据放到根节点(索引0位置),然后将未知0与N-2位置的数据兑换,

那么最大(最小)的数据就跑到倒数第二的位置去了

……………………以此类推就实现排序了

package example;

import java.util.Arrays;
import java.util.Random;

public class Test {

    public static void main(String[] args) {
        Random rd = new Random();
        int[] arrays = new int[10];
        for (int i = 0; i < arrays.length; i++) {
            arrays[i] = rd.nextInt(100);
        }
        System.out.println("排序前:" + Arrays.toString(arrays));
        heapSort(arrays);
        System.out.println("排序后:" + Arrays.toString(arrays));

    }

    public static void heapSort(int[] arrays) {
        for (int i = 0; i < arrays.length - 1; i++) {
            buildMaxHeap(arrays, arrays.length - 1 - i);
            swap(arrays, 0, arrays.length - 1 - i);
        }
    }

    private static void buildMaxHeap(int[] arrays, int lastIndex) {
        for (int i = (lastIndex - 1) / 2; i >= 0; i--) {
            int k = i;
            while (2 * k + 1 <= lastIndex) {//当前k节点存在子节点
                int biggerIndex = 2 * k + 1;//左节点

                if (biggerIndex < lastIndex) {//左节点索引小于最大索引未知、说明存在右节点且右节点索引等于lastIndex
                    if (arrays[biggerIndex] < arrays[biggerIndex + 1]) {
                        biggerIndex++;
                    }
                }

                if (arrays[k] < arrays[biggerIndex]) {
                    swap(arrays, k, biggerIndex);
                    k = biggerIndex;
                } else {
                    break;
                }

            }//end while
        }//end for
    }

    private static void swap(int[] arrays, int i, int j) {
        int temp;
        temp = arrays[i];
        arrays[i] = arrays[j];
        arrays[j] = temp;
    }
}

run:
排序前:[77, 69, 10, 97, 61, 56, 35, 44, 89, 81]
排序后:[10, 35, 44, 56, 61, 69, 77, 81, 89, 97]
成功构建 (总时间: 0 秒)

假设有N项数据,那么就要进行N-1次建堆,每次建堆耗时log2n,起时间效率为O(nlog2n);但是其空间效率很高,为O(1);堆排序是不稳定的

3、冒泡排序

冒泡排序时候,数据要不断的进行交换,属于交换排序

第一趟:比较0与1、1月2…………n-2与n-1,只要第一个数对第二个数大,就交换位置,那么最后一个就是最大的

第二趟:比较0与1、1月2…………n-3与n-2,只要第一个数对第二个数大,就交换位置,那么最后一个就是倒数第二大的

………………以此类推

package example;

import java.util.Arrays;
import java.util.Random;

public class Test {

    public static void main(String[] args) {
        Random rd = new Random();
        int[] arrays = new int[10];
        for (int i = 0; i < arrays.length; i++) {
            arrays[i] = rd.nextInt(100);
        }
        System.out.println("排序前:" + Arrays.toString(arrays));
        bubbleSort(arrays);
        System.out.println("排序后:" + Arrays.toString(arrays));

    }

    private static void bubbleSort(int[] arrays) {
        for (int i = 0; i < arrays.length - 1; i++) {
            boolean flag = false;
            for (int j = 0; j < arrays.length - 1 - i; j++) {
                if (arrays[j] > arrays[j + 1]) {
                    swap(arrays, j, j + 1);
                    flag = true;
                }//end if
            }//end for inner
            if (!flag) {//某一趟没有发生交换说明已经排好序了
                break;
            }
        }//end for outer
    }

    private static void swap(int[] arrays, int i, int j) {
        int temp;
        temp = arrays[i];
        arrays[i] = arrays[j];
        arrays[j] = temp;
    }
}
run:
排序前:[66, 8, 74, 61, 6, 99, 60, 73, 64, 53]
排序后:[6, 8, 53, 60, 61, 64, 66, 73, 74, 99]
成功构建 (总时间: 0 秒)

冒泡排序最坏情况下:需要做n*(n-1)/2比较;移动次数n*(n-1)*3/2;空间利用率O(1);

冒泡排序是稳定的

4、快速排序

快速排序是一种速度非常快的交换排序方法。

思路:从待排序数据中任取一个数据(第一个)做为分界值,所有比它小的放到左边,大的放到右边;

这样第一趟就形成了两个自序列,然后分别对这两个自序列递归进行,直到每一个子序列只有一个元素就可以了


package example;

import java.util.Arrays;
import java.util.Random;

public class Test {

    public static void main(String[] args) {
        Random rd = new Random();
        int[] arrays = new int[10];
        for (int i = 0; i < arrays.length; i++) {
            arrays[i] = rd.nextInt(100);
        }
        System.out.println("排序前:" + Arrays.toString(arrays));
        quickSort(arrays);
        System.out.println("排序后:" + Arrays.toString(arrays));

    }

    private static void quickSort(int[] arrays) {
        subSort(arrays, 0, arrays.length - 1);
    }

    private static void subSort(int[] arrays, int start, int end) {
        if (start < end) {
            int base = arrays[start];//首元素做为分界值
            int left = start + 1;
            int right = end;

            while (1 == 1) {
                while (left < end && arrays[left] <= base) {//从左到右找到大于base的
                    left++;
                }
                while (right > start && arrays[right] >= base) {//从右到左找到小于base的
                    right--;
                }

                if (left < right) {
                    swap(arrays, left, right);
                } else {
                    break;
                }
            }//end while
            swap(arrays, start, right);

            subSort(arrays, start, right - 1);//递归左边
            subSort(arrays, right + 1, end);//递归右边
        }//end if
    }

    private static void swap(int[] arrays, int i, int j) {
        int temp;
        temp = arrays[i];
        arrays[i] = arrays[j];
        arrays[j] = temp;
    }
}
run:
排序前:[80, 87, 32, 30, 75, 35, 60, 17, 74, 59]
排序后:[17, 30, 32, 35, 59, 60, 74, 75, 80, 87]
成功构建 (总时间: 0 秒)


快速排序是不稳定的,空间利用率O(log2n) ,时间效率很高

5、直接插入排序

思路:依次将需要排序的数据按其关键字的大小插入前面的有序序列

对于一个有N个元素的序列;

1、第一趟,将第二个元素插入前面序列,目前前面那个序列只有一个元素

2、第二趟,将第三个元素插入前面序列,前面有两个数据,

…………N-1次之后就实现了排序

package example;

import java.util.Arrays;
import java.util.Random;

public class Test {

    public static void main(String[] args) {
        Random rd = new Random();
        int[] arrays = new int[10];
        for (int i = 0; i < arrays.length; i++) {
            arrays[i] = rd.nextInt(100);
        }
        System.out.println("排序前:" + Arrays.toString(arrays));
        insertSort(arrays);
        System.out.println("排序后:" + Arrays.toString(arrays));

    }

    private static void insertSort(int[] arrays) {
        for (int i = 1; i < arrays.length; i++) {
            int temp = arrays[i];
            if (arrays[i] < arrays[i - 1]) {
                int j = i - 1;
                //先整体后移一步然后再插入
                for (; j >= 0 && arrays[j] > temp; j--) {
                    arrays[j + 1] = arrays[j];
                }//end for inner
                arrays[j + 1] = temp;
            }
        }//end for outer
    }

    private static void swap(int[] arrays, int i, int j) {
        int temp;
        temp = arrays[i];
        arrays[i] = arrays[j];
        arrays[j] = temp;
    }
}
run:
排序前:[71, 60, 29, 5, 57, 88, 89, 62, 37, 96]
排序后:[5, 29, 37, 57, 60, 62, 71, 88, 89, 96]
成功构建 (总时间: 0 秒)

直接插入时间效率并不高,为O(n*n),但是控件利用率高,为O(1),直接插入排序是稳定的。

6、二分插入排序

1、计算0—i-1索引的中间点,用i处的元素与(0+i-1)/2出的元素进行比较,如果i出的元素大,则在(0+i-1)/2—i-1范围内搜索;反之在0—(0+i-1)/2范围内搜索

2、按照步骤1不断的进行此操作,范围缩小到1/2,1/4,1/8,从而决定出第i个元素的插入位置

3、一旦确认出i个元素的插入位置,下面只需要将元素整体后移一步,然后将i个元素放进去

package example;

import java.util.Arrays;
import java.util.Random;

public class Test {

    public static void main(String[] args) {
        Random rd = new Random();
        int[] arrays = new int[10];
        for (int i = 0; i < arrays.length; i++) {
            arrays[i] = rd.nextInt(100);
        }
        System.out.println("排序前:" + Arrays.toString(arrays));
        binaryInsertSort(arrays);
        System.out.println("排序后:" + Arrays.toString(arrays));

    }

    private static void binaryInsertSort(int[] arrays) {
        for (int i = 1; i < arrays.length; i++) {
            int temp = arrays[i];
            int left = 0;
            int right = i - 1;
            while (left <= right) {
                int middle = (left + right) / 2;
                if (temp > arrays[middle]) {
                    left = middle + 1;
                } else {
                    right = middle - 1;
                }
            }//end while

            for (int j = i; j > left; j--) {
                arrays[j] = arrays[j - 1];
            }//end for inner
            arrays[left] = temp;
        }//end for
    }

    private static void swap(int[] arrays, int i, int j) {
        int temp;
        temp = arrays[i];
        arrays[i] = arrays[j];
        arrays[j] = temp;
    }
}
run:
排序前:[81, 63, 51, 73, 55, 46, 23, 12, 18, 73]
排序后:[12, 18, 23, 46, 51, 55, 63, 73, 73, 81]
成功构建 (总时间: 0 秒)

二分插入排序与直接插入排序效果差不多,只是速度更快


7、Shell排序

Shell排序对直接插入排序进行了改进:通过加大排序中元素之间的间隔,并在这些有间隔的元素之间插入排序,从而使数据项大跨度移动。当这些数据经过一次排序之后,Shell排序算法减小数据项的间隔在排序,依次进行下去,这些间隔被成为增量。

h=h*3+1

package example;

import java.util.Arrays;
import java.util.Random;

public class Test {

    public static void main(String[] args) {
        Random rd = new Random();
        int[] arrays = new int[10];
        for (int i = 0; i < arrays.length; i++) {
            arrays[i] = rd.nextInt(100);
        }
        System.out.println("排序前:" + Arrays.toString(arrays));
        shellSort(arrays);
        System.out.println("排序后:" + Arrays.toString(arrays));

    }

    private static void shellSort(int[] arrays) {
        int arrayLength = arrays.length;
        int h = 1;
        while (h < arrayLength / 3) {
            h = h * 3 + 1;
        }
        while (h > 0) {
            for (int i = h; i < arrayLength; i++) {
                int temp = arrays[i];
                if (arrays[i] < arrays[i - h]) {
                    int j = i - h;
                    //整体后移一位
                    for (; j >= 0 && arrays[j] > temp; j -= h) {
                        arrays[j + h] = arrays[j];
                    }//end for inner
                    arrays[j + h] = temp;
                }
            }//end for outer

            h = (h - 1) / 3;
        }//end while
    }

    private static void swap(int[] arrays, int i, int j) {
        int temp;
        temp = arrays[i];
        arrays[i] = arrays[j];
        arrays[j] = temp;
    }
}
run:
排序前:[36, 82, 11, 7, 5, 26, 48, 37, 11, 62]
排序后:[5, 7, 11, 11, 26, 36, 37, 48, 62, 82]
成功构建 (总时间: 0 秒)

Shell排序是直接插入排序的改进型,因此是稳定的,速度更快

8、归并排序
 归并排序是将两个有序的序列合并在一起组成一个新的序列。

首先将排序序列堪称N个长度为1的序列,首先做两个两个的合并,得到N/2个长度为2的有序序列,如此循环………………最终得到一个长度为N的序列。

 

package example;

import java.util.Arrays;
import java.util.Random;

public class Test {

    public static void main(String[] args) {
        Random rd = new Random();
        int[] arrays = new int[10];
        for (int i = 0; i < arrays.length; i++) {
            arrays[i] = rd.nextInt(100);
        }
        System.out.println("排序前:" + Arrays.toString(arrays));
        mergeSort(arrays);
        System.out.println("排序后:" + Arrays.toString(arrays));

    }

    private static void mergeSort(int[] arrays) {
        sort(arrays, 0, arrays.length - 1);
    }

    private static void sort(int[] arrays, int left, int right) {
        if (left < right) {
            //求中间位置
            int center = (left + right) / 2;
            //对左边数组排序
            sort(arrays, left, center);
            //对右边数组排序
            sort(arrays, center + 1, right);
            //合并
            merge(arrays, left, center, right);
        }
    }

    private static void merge(int[] arrays, int left, int center, int right) {
        int[] tempArray = new int[arrays.length];
        int middle = center + 1;
        int tmpIndex = left;
        int cpIndex = left;

        while (left <= center && middle <= right) {
            //选出两个数组中最小的那个放到中间数组
            if (arrays[middle] >= arrays[left]) {
                tempArray[tmpIndex++] = arrays[left++];
            } else {
                tempArray[tmpIndex++] = arrays[middle++];
            }
        }//end while 

        //剩余数据依次放入中间数组
        while (middle <= right) {
            tempArray[tmpIndex++] = arrays[middle++];
        }
        while (left <= center) {
            tempArray[tmpIndex++] = arrays[left++];
        }

        //将中间数组的数据复制到原数组            
        while (cpIndex <= right) {
            arrays[cpIndex] = tempArray[cpIndex++];
        }
    }
}
run:
排序前:[41, 98, 45, 20, 90, 56, 64, 80, 27, 13]
排序后:[13, 20, 27, 41, 45, 56, 64, 80, 90, 98]
成功构建 (总时间: 0 秒)

归并排序的空间效率很差,因为需要一个中间数组,时间复杂度为O(nlog2n);归并排序是稳定的。

9、桶式排序

桶式排序不再是基于比较的排序,其需要满足以下几个条件:

(1)、待排数据的所有值处于一个可以枚举的范围之内

(2)、这个枚举范围不应该很大,否则开销很大


package example;

import java.util.Arrays;
import java.util.Random;

public class Test {

    public static void main(String[] args) {
        Random rd = new Random();
        int[] arrays = new int[10];
        for (int i = 0; i < arrays.length; i++) {
            arrays[i] = rd.nextInt(100);
        }
        System.out.println("排序前:" + Arrays.toString(arrays));
        bucketSort(arrays, 1, 100);
        System.out.println("排序后:" + Arrays.toString(arrays));

    }

    private static void bucketSort(int[] arrays, int min, int max) {
        int[] tempArray = new int[arrays.length];
        int[] buckets = new int[max - min];

        //计算每个元素在序列中出现的次数
        for (int i = 0; i < arrays.length; i++) {
            buckets[arrays[i] - min]++;
        }

        //计算桶内各元素在有序序列中的位置
        for (int i = 1; i < max - min; i++) {
            buckets[i] = buckets[i] + buckets[i - 1];
        }

        //将待排数据全部复制到中间数组里面
        System.arraycopy(arrays, 0, tempArray, 0, arrays.length);

        //根据buckets数组的信息将待排列的数据放入对应的位置
        for (int k = arrays.length - 1; k >= 0; k--) {
            arrays[--buckets[tempArray[k] - min]] = tempArray[k];
        }
    }
   }
run:
排序前:[83, 40, 66, 68, 34, 31, 20, 51, 13, 75]
排序后:[13, 20, 31, 34, 40, 51, 66, 68, 75, 83]
成功构建 (总时间: 0 秒)

桶式排序的时间效率很高,但是空间开销太大,因为需要两个中间数组;桶式排序是稳定的。
 

10、基数排序不是单一的排序算法,需要依赖其他排序算法,而这个排序算法必须是稳定的。基数排序将待排列数据分成多个关键字排序,基数排序的实质是关键字排序。

package example;

import java.util.Arrays;
import java.util.Random;

public class Test {

    public static void main(String[] args) {
        Random rd = new Random();
        int[] arrays = new int[10];
        for (int i = 0; i < arrays.length; i++) {
            arrays[i] = rd.nextInt(100);
        }
        System.out.println("排序前:" + Arrays.toString(arrays));
        radixSort(arrays, 10, 2);
        System.out.println("排序后:" + Arrays.toString(arrays));

    }

    /**
     * 基数排序ASC(中间使用桶式排序)
     *
     * @param arrays 待排数组ASC
     * @param radix 关键字拆分的进制 10代表十进制
     * @param count 将关键字拆分成几个关键字
     */
    private static void radixSort(int[] arrays, int radix, int count) {
        int[] tempArray = new int[arrays.length];
        int[] buckets = new int[radix];

        for (int i = 0, rate = 1; i < count; i++) {
            Arrays.fill(buckets, 0);//重置数组,开始统计下一个关键字
            System.arraycopy(arrays, 0, tempArray, 0, arrays.length);//将待排数据复制到中间数组
            for (int j = 0; j < arrays.length; j++) {
                int key = (tempArray[j] / rate) % radix;
                buckets[key]++;
            }

            for (int j = 1; j < radix; j++) {
                buckets[j] = buckets[j] + buckets[j - 1];
            }

            //按子关键字对数据进行排序
            for (int k = arrays.length - 1; k >= 0; k--) {
                int key = (tempArray[k] / rate) % radix;
                arrays[--buckets[key]] = tempArray[k];
            }

            rate *= radix;
        }//end for outer
    }
}
run:
排序前:[98, 39, 38, 2, 84, 39, 87, 88, 35, 79]
排序后:[2, 35, 38, 39, 39, 79, 84, 87, 88, 98]
成功构建 (总时间: 0 秒)

 

排序法 平均时间 最差情形 稳定度 额外空间 备注
冒泡 O(n2)     O(n2) 稳定 O(1) n小时较好
交换     O(n2)     O(n2) 不稳定 O(1) n小时较好
选择 O(n2) O(n2) 不稳定 O(1) n小时较好
插入 O(n2) O(n2) 稳定 O(1) 大部分已排序时较好
基数 O(logRB) O(logRB) 稳定 O(n)

B是真数(0-9),

R是基数(个十百)

Shell O(nlogn) O(ns) 1<s<2 不稳定 O(1) s是所选分组
快速 O(nlogn) O(n2) 不稳定 O(nlogn) n大时较好
归并 O(nlogn) O(nlogn) 稳定 O(1) n大时较好
O(nlogn) O(nlogn) 不稳定 O(1) n大时较好

 

package sortUtility;

import java.util.Arrays;

/**
 *
 * @author Administrator
 */
public class SortUtility {

//////////////////////////////////选择排序-beign/////////////////////////////////////////////
    /**
     * @deprecated 直接选择排序ASC
     * @param arrays 需要排序的数组
     */
    public void directSelectSort(int[] arrays) {
        for (int i = 0; i < arrays.length - 1; i++) {
            for (int j = i + 1; j < arrays.length; j++) {
                if (arrays[i] > arrays[j]) {
                    swap(arrays, i, j);
                }//end if
            }//end for inner
        }//end for outer
    }

    /**
     * @deprecated 优化的直接选择排序ASC(减少数据交换次数)
     * @param arrays 需要排序的数组
     */
    public void directSelectSortNew(int[] arrays) {
        int index;
        for (int i = 0; i < arrays.length - 1; i++) {
            index = i;
            for (int j = i + 1; j < arrays.length; j++) {
                if (arrays[index] > arrays[j]) {
                    index = j;
                }
            }
            if (index != i) {
                swap(arrays, i, index);
            }
        }
    }

    public void heapSort(int[] arrays) {
        for (int i = 0; i < arrays.length - 1; i++) {
            buildMaxHeap(arrays, arrays.length - 1 - i);
            swap(arrays, 0, arrays.length - 1 - i);
        }
    }

    /**
     * @deprecated 建立大顶堆(根节点>=左子节点 AND 根节点>=右子节点)
     * @param arrays 需排序数组
     * @param lastIndex 最后一个节点
     */
    private void buildMaxHeap(int[] arrays, int lastIndex) {
        for (int i = (lastIndex - 1) / 2; i >= 0; i--) {
            int k = i;
            while (2 * k + 1 <= lastIndex) {//当前k节点存在子节点
                int biggerIndex = 2 * k + 1;//左节点

                if (biggerIndex < lastIndex) {//左节点索引小于最大索引未知、说明存在右节点且右节点索引等于最大索引
                    if (arrays[biggerIndex] < arrays[biggerIndex + 1]) {
                        biggerIndex++;
                    }
                }

                if (arrays[k] < arrays[biggerIndex]) {
                    swap(arrays, k, biggerIndex);
                    k = biggerIndex;
                } else {
                    break;
                }

            }//end while
        }//end for
    }
//////////////////////////////////选择排序-end/////////////////////////////////////////////
//////////////////////////////////交换排序-begin/////////////////////////////////////////////

    /**
     * @deprecated 冒泡排序ASC
     * @param arrays 需排序数组
     */
    public void bubbleSort(int[] arrays) {
        for (int i = 0; i < arrays.length - 1; i++) {
            boolean flag = false;
            for (int j = 0; j < arrays.length - 1 - i; j++) {
                if (arrays[j] > arrays[j + 1]) {
                    swap(arrays, j, j + 1);
                    flag = true;
                }//end if
            }//end for inner
            if (!flag) {//某一趟没有发生交换说明已经排好序了
                break;
            }
        }//end for outer
    }

    /**
     * @deprecated 快速排序ASC
     * @param arrays 需排序数组
     */
    public void quickSort(int[] arrays) {
        subSort(arrays, 0, arrays.length - 1);
    }

    private void subSort(int[] arrays, int start, int end) {
        if (start < end) {
            int base = arrays[start];//首元素做为分界值
            int left = start + 1;
            int right = end;

            while (1 == 1) {
                while (left < end && arrays[left] <= base) {//从左到右找到大于base的
                    left++;
                }
                while (right > start && arrays[right] >= base) {//从右到左找到小于base的
                    right--;
                }

                if (left < right) {
                    swap(arrays, left, right);
                } else {
                    break;
                }
            }//end while
            swap(arrays, start, right);

            subSort(arrays, start, right - 1);//递归左边
            subSort(arrays, right + 1, end);//递归右边
        }//end if
    }
//////////////////////////////////交换排序-end/////////////////////////////////////////////

//////////////////////////////////插入排序-begin/////////////////////////////////////////////
    /**
     * @deprecated 直接插入排序ASC
     * @param arrays 需排序数组
     */
    public void insertSort(int[] arrays) {
        for (int i = 1; i < arrays.length; i++) {
            int temp = arrays[i];
            if (arrays[i] < arrays[i - 1]) {
                int j = i - 1;
                //先整体后移一步然后再插入
                for (; j >= 0 && arrays[j] > temp; j--) {
                    arrays[j + 1] = arrays[j];
                }//end for inner
                arrays[j + 1] = temp;
            }
        }//end for outer
    }

    /**
     * @deprecated 二分插入排序ASC
     * @param arrays 需排序数组
     */
    public void binaryInsertSort(int[] arrays) {
        for (int i = 1; i < arrays.length; i++) {
            int temp = arrays[i];
            int left = 0;
            int right = i - 1;
            while (left <= right) {
                int middle = (left + right) / 2;
                if (temp > arrays[middle]) {
                    left = middle + 1;
                } else {
                    right = middle - 1;
                }
            }//end while

            for (int j = i; j > left; j--) {
                arrays[j] = arrays[j - 1];
            }//end for inner
            arrays[left] = temp;
        }//end for
    }

    /**
     * @deprecated Shell排序ASC
     * @param arrays 需排序数组
     */
    public void shellSort(int[] arrays) {
        int arrayLength = arrays.length;
        int h = 1;
        while (h < arrayLength / 3) {
            h = h * 3 + 1;
        }
        while (h > 0) {
            for (int i = h; i < arrayLength; i++) {
                int temp = arrays[i];
                if (arrays[i] < arrays[i - h]) {
                    int j = i - h;
                    //整体后移一位
                    for (; j >= 0 && arrays[j] > temp; j -= h) {
                        arrays[j + h] = arrays[j];
                    }//end for inner
                    arrays[j + h] = temp;
                }
            }//end for outer

            h = (h - 1) / 3;
        }//end while
    }
//////////////////////////////////插入排序-end/////////////////////////////////////////////    
//////////////////////////////////归并排序-begin///////////////////////////////////////////

    /**
     * @deprecated 归并排序ASC
     * @param arrays 待排数组
     */
    public void mergeSort(int[] arrays) {
        sort(arrays, 0, arrays.length - 1);
    }

    /**
     * @deprecated 递归排序
     * @param arrays 待排数组
     * @param left 数组第一个元素索引
     * @param right 数组最后一个元素索引
     */
    private void sort(int[] arrays, int left, int right) {
        if (left < right) {
            //求中间位置
            int center = (left + right) / 2;
            //对左边数组排序
            sort(arrays, left, center);
            //对右边数组排序
            sort(arrays, center + 1, right);
            //合并
            merge(arrays, left, center, right);
        }
    }

    /**
     * @deprecated 将两个数组归并
     * @param arrays 待排数组
     * @param left 左数组第一个元素索引
     * @param center 左数组最后一个元素 center+1为右数组第一个元素索引
     * @param right 右数组最后一个元素索引
     */
    private void merge(int[] arrays, int left, int center, int right) {
        int[] tempArray = new int[arrays.length];
        int middle = center + 1;
        int tmpIndex = left;
        int cpIndex = left;

        while (left <= center && middle <= right) {
            //选出两个数组中最小的那个放到中间数组
            if (arrays[middle] >= arrays[left]) {
                tempArray[tmpIndex++] = arrays[left++];
            } else {
                tempArray[tmpIndex++] = arrays[middle++];
            }
        }//end while 

        //剩余数据依次放入中间数组
        while (middle <= right) {
            tempArray[tmpIndex++] = arrays[middle++];
        }
        while (left <= center) {
            tempArray[tmpIndex++] = arrays[left++];
        }

        //将中间数组的数据复制到原数组            
        while (cpIndex <= right) {
            arrays[cpIndex] = tempArray[cpIndex++];
        }
    }
//////////////////////////////////归并排序-end/////////////////////////////////////////////    
//////////////////////////////////桶式排序-begin///////////////////////////////////////////

    /**
     * @deprecated 桶式排序ASC
     * @param min 枚举范围最小值
     * @param max 枚举范围最大值
     */
    public void bucketSort(int[] arrays, int min, int max) {
        int[] tempArray = new int[arrays.length];
        int[] buckets = new int[max - min];

        //计算每个元素在序列中出现的次数
        for (int i = 0; i < arrays.length; i++) {
            buckets[arrays[i] - min]++;
        }

        //计算桶内各元素在有序序列中的位置
        for (int i = 1; i < max - min; i++) {
            buckets[i] = buckets[i] + buckets[i - 1];
        }

        //将待排数据全部复制到中间数组里面
        System.arraycopy(arrays, 0, tempArray, 0, arrays.length);

        //根据buckets数组的信息将待排列的数据放入对应的位置
        for (int k = arrays.length - 1; k >= 0; k--) {
            arrays[--buckets[tempArray[k] - min]] = tempArray[k];
        }
    }
//////////////////////////////////桶式排序-end/////////////////////////////////////////////    

//////////////////////////////////基数排序-begin///////////////////////////////////////////
    /**
     * 基数排序ASC(中间使用桶式排序)
     *
     * @param arrays 待排数组ASC
     * @param radix 关键字拆分的进制 10代表十进制
     * @param count 将关键字拆分成几个关键字
     */
    public void radixSort(int[] arrays, int radix, int count) {
        int[] tempArray = new int[arrays.length];
        int[] buckets = new int[radix];

        for (int i = 0, rate = 1; i < count; i++) {
            Arrays.fill(buckets, 0);//重置数组,开始统计下一个关键字
            System.arraycopy(arrays, 0, tempArray, 0, arrays.length);//将待排数据复制到中间数组
            for (int j = 0; j < arrays.length; j++) {
                int key = (tempArray[j] / rate) % radix;
                buckets[key]++;
            }

            for (int j = 1; j < radix; j++) {
                buckets[j] = buckets[j] + buckets[j - 1];
            }

            //按子关键字对数据进行排序
            for (int k = arrays.length - 1; k >= 0; k--) {
                int key = (tempArray[k] / rate) % radix;
                arrays[--buckets[key]] = tempArray[k];
            }

            rate *= radix;
        }//end for outer
    }
//////////////////////////////////基数排序-end/////////////////////////////////////////////   

    /**
     * @deprecated 交换数据
     */
    private void swap(int[] arrays, int i, int j) {
        int temp;
        temp = arrays[i];
        arrays[i] = arrays[j];
        arrays[j] = temp;
    }
}


 

 

你可能感兴趣的:(常用排序算法使用)