常用排序算法使用

常用排序算法有:

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是基数(个十百)

ShellO(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;
    }
}


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值