常用排序算法及Java实现

排序算法,可以分为内部排序和外部排序两大种。这篇文章主要对内部排序进行介绍。内部排序又分为两类,基于比较的非线性时间类,和非比较的线性时间类。前一类又可以分为四种,交换排序(包括冒泡排序和快速排序),插入排序(包括简单插入排序和希尔排序),选择排序(包括简单选择排序和堆排序)以及归并排序;后者主要包含三种,计数排序,桶排序和基数排序。

总体来说,快排、堆排和归并排序是非线性时间中最快的三种。一般认为,快排的时间效率会比堆排更好。另一方面,快排和堆排都是不稳定的算法,只有归并排序、冒泡排序和插入排序是稳定的算法,因此Java中的sort算法在实现的时候,有一个阈值,大概是60左右。数组长度低于这个阈值的,直接使用插入排序;高于这个阈值的,如果元素是基本数据类型,救使用快排,如果是引用数据类型,就使用归并排序。而对于基于比较的排序算法,都很依赖于数据本身的分布——在数据均匀分布的情况下,效率可以很高。计数排序是用来排序0到100之间的数字的最好的算法,但是它不适合按字母顺序排序人名;计数排序则要求对每一位使用的排序算法都是稳定的。

下面我们对这九种算法进行详细的介绍。为了方便,我们设定所有的排序都基于整形数组,需要按照从小到大的顺序进行排列。在这些排序算法中,有一些公用的操作,比如元素交换,元素打印,寻找最大值最小值等,为了代码的复用,我们定义了工具类Tools,首先给出Tools类的代码。

 1 public class Tools {
 2     public static void swap(int[] arr, int i, int j) {
 3         int tmp = arr[i];
 4         arr[i] = arr[j];
 5         arr[j] = tmp;
 6     }
 7 
 8     public static void printArray(int[] arr) {
 9         int i = 0;
10         System.out.print("[");
11         for (; i < arr.length - 1; i++) {
12             System.out.print(arr[i] + ",");
13         }
14         System.out.println(arr[i] + "]");
15     }
16 
17     public static int findMax(int[] arr) {
18         int max = Integer.MIN_VALUE;
19         for (int num : arr) {
20             max = Math.max(max, num);
21         }
22         return max;
23     }
24 
25     public static int findMin(int[] arr) {
26         int min = Integer.MAX_VALUE;
27         for (int num : arr) {
28             min = Math.min(min, num);
29         }
30         return min;
31     }
32 }

1、交换算法

1.1 冒泡算法

整体思路:第i轮排序,从第0号元素到第(length-1-i)号元素,进行相邻元素的比较,并将较大的元素不断交换到后一位置。

特点:第i轮排序完成后,第i个最大值出现在下标为(length-1-i)的位置。

时间复杂度:最坏:O(n^2),平均:O(n^2),最好:O(n);

空间复杂度:O(1)

稳定性:稳定,但是当条件变为arr[j] >= arr[j + 1]时,就不稳定了

Java实现:

 1 /**
 2  *  3  *
 4  *         以整型数组为例,通过冒泡排序将数组中的元素按从小到大的顺序进行排列
 5  *         思路:第i轮排序,从第0号元素到第(length-1-i)号元素,进行相邻元素的比较,并将较大的元素交换到后一位置。
 6  *         特点:第i轮排序结束后,第i个最大值出现在下标为(length-1-i)的位置
 7  *         时间复杂度:最坏:O(n^2),平均:O(n^2),最好:O(n);
 8  *         空间复杂度:O(1)
 9  *         稳定性:稳定,但是当条件变为arr[j] >= arr[j + 1]时,就不稳定了
10  */
11 public class BubbleSort {
12     public static void bubbleSort(int[] arr) {
13         for (int i = 0; i < arr.length - 1; i++) {
14             for (int j = 0; j < arr.length - 1 - i; j++) {
15                 if (arr[j] > arr[j + 1]) {
16                     Tools.swap(arr, j, j + 1);
17                 }
18             }
19         }
20     }
21 
22     public static void main(String[] args) {
23         int[] arr = { 5, 6, 8, 3, 2, 1, 9, 7, 2 };
24         System.out.println("before sorting:");
25         Tools.printArray(arr);
26         bubbleSort(arr);
27         System.out.println("after sorting:");
28         Tools.printArray(arr);
29     }
30 }

1.2 快速排序

整体思路:通过递归的方式,不断将数组分为两部分,主元左边的都比主元小,右边的都比主元大。特点:每一轮的排序结束后,数组中的某一部分就会成为有序的序列。

时间复杂度:最坏O(n^2),平均O(nlog2n),最好O(nlog2n)。

空间复杂度:O(nlog2n),主要是由于递归调用造成的栈内存的使用。

稳定性:不稳定。

在每一轮的排序过程中,注意首先从右往左进行查找;在跳出循环后,将low索引指向的位置作为主元交换的位置。

Java实现:

 1 /**
 2  *  3  *
 4  *         以整型数组为例,通过快速排序将数组中的元素按从小到大的顺序进行排列
 5  *         思路:通过递归的方式,不断将数组分为两部分,主元左边的都比主元小,右边的都比主元大。
 6  *         特点:每一轮的排序结束后,数组中的某一部分就会成为有序的序列。
 7  *         时间复杂度:最坏O(n^2),平均O(nlog2n),最好O(nlog2n)
 8  *         空间复杂度:O(nlog2n),主要是由于递归调用造成的栈内存的使用
 9  *         稳定性:不稳定
10  *         
11  *         在每一轮的排序过程中,注意首先从右往左进行查找;在跳出循环后,将low索引指向的位置作为主元交换的位置
12  *         
13  */
14 public class QuickSort {
15     public static void quickSort(int[] arr, int first, int last) {
16         if (last < first) {
17             return;
18         }
19         int low = first;
20         int high = last;
21         int pivot = arr[first];
22         while (high > low) {
23             while (high > low && arr[high] >= pivot)
24                 high--;
25             while (high > low && arr[low] <= pivot)
26                 low++;
27             if (high > low) {
28                 Tools.swap(arr, low, high);
29             }
30         }
31 
32         Tools.swap(arr, first, low);
33         quickSort(arr, first, low - 1);
34         quickSort(arr, low + 1, last);
35     }
36 
37     public static void quickSort(int[] arr) {
38         quickSort(arr, 0, arr.length - 1);
39     }
40 
41     public static void main(String[] args) {
42         int[] arr = { 1, 5, 6, 8, 3, 2, 1, 9, 7, 2, 1, 1 };
43         //        int[] arr = { 5, 6, 8, 3, 2, 1, 9, 7, 2 };
44         System.out.println("before sorting:");
45         Tools.printArray(arr);
46         quickSort(arr);
47         System.out.println("after sorting:");
48         Tools.printArray(arr);
49     }
50 }

2. 选择排序

2.1 简单选择排序

整体思路:第i轮排序,找到第i个最小值,将其交换到下标为i的位置。

特点:第i轮排序结束后,第i个最小值出现在下标为i的位置。

时间复杂度:三种情况都是O(n^2)。

空间复杂度:O(1)。

稳定性:不稳定

在每一轮选择最小元素的过程中,可以在每次符合条件时都进行换位,也可以将这一轮中最小值的索引记下来,这一轮结束时进行一次换位。这样减少了在堆内存中的操作,更加高效。

Java实现:

 1 /**
 2  * @author hr
 3  * 
 4  *         以整型数组为例,通过选择排序将数组中的元素按从小到大的顺序进行排列 
 5  *         思路:第i轮排序,找到第i个最小值,将其交换到下标为i的位置。
 6  *         特点:第i轮排序结束后,第i个最小值出现在下标为i的位置
 7  *         
 8  *         在每一轮选择最小元素的过程中,可以在每次符合条件时都进行换位,也可以将这一轮中最小值的
 9  *         索引记下来,这一轮结束时进行一次换位。这样减少了在堆内存中的操作,更加高效。
10  *         时间复杂度:三种情况都是O(n^2)
11  *         空间复杂度:O(1)
12  *         稳定性:不稳定
13  *         
14  */
15 public class SelectionSort {
16     public static void selectionSort(int[] arr) {
17         for (int i = 0; i < arr.length - 1; i++) {
18             int minIndex = i;
19             for (int j = i + 1; j < arr.length; j++) {
20                 if (arr[j] < arr[minIndex])
21                     minIndex = j;
22             }
23             if (minIndex != i)
24                 Tools.swap(arr, i, minIndex);
25         }
26     }
27 
28     public static void main(String[] args) {
29         int[] arr = { 5, 6, 8, 3, 2, 1, 9, 7, 2 };
30         System.out.println("before sorting:");
31         Tools.printArray(arr);
32         selectionSort(arr);
33         System.out.println("after sorting:");
34         Tools.printArray(arr);
35     }
36 }

2.2 堆排序

整体思路:首先,将给定的数组建立起一个大顶堆,这也意味着找到了最大的元素;然后,将最大的元素换到堆的末尾(也就是数组的末尾),将剩下的元素重新建立起一个大顶堆,不断找到剩余元素中的最大值。

特点:第i轮排序结束后,第i个最大值出现在下标为length - i的位置 。

时间复杂度:三种情况都是O(nlog2n)。

空间复杂度:O(1)。

稳定性:不稳定。

在最开始建立大顶堆时,只需要遍历前半部分数组即可,初始的循环遍历条件设为(length - 1) / 2,直到0为止。随后每次找最大值,也是从后面的元素开始向上遍历。而对大顶堆进行调整的时候,则是从给定的元素开始不断向下进行调整。每次对堆进行调整的循环停止条件为:当前节点不存在左孩子节点,或者当前节点值已经是三个节点中的最大值了。

Java实现:

/**
 * @author hr
 * 
 *         以整型数组为例,通过堆排序将数组中的元素按从小到大的顺序进行排列 
 *         思路:首先,将给定的数组建立起一个大顶堆,这也意味着找到了最大的元素;然后,将最大的元素换到堆的末尾
 *         (也就是数组的末尾),将剩下的元素重新建立起一个大顶堆,不断找到剩余元素中的最大值。
 *         特点:第i轮排序结束后,第i个最大值出现在下标为length - i的位置
 *         
 *         在最开始建立大顶堆时,只需要遍历前半部分数组即可,初始的循环遍历条件设为(length - 1) / 2,直到0为止
 *         随后每次找最大值,也是从后面的元素开始向上遍历。
 *         而对大顶堆进行调整的时候,则是从给定的元素开始不断向下进行调整。
 *         时间复杂度:三种情况都是O(nlog2n)
 *         空间复杂度:O(1)
 *         稳定性:不稳定
 *         
 */
public class HeapSort {
    private static void heapify(int[] arr, int index, int heapSize) {
        int left = 2 * index + 1;
        int right = 2 * index + 2;
        int largest = index;
        while (left < heapSize) {
            if (arr[left] > arr[largest])
                largest = left;
            if (right < heapSize && arr[right] > arr[index])
                largest = right;
            if (index != largest) {
                Tools.swap(arr, index, largest);
                index = largest;
                left = 2 * index + 1;
                right = 2 * index + 2;
            } else
                break;
        }
    }

    public static void buildHeap(int[] arr) {
        for (int i = (arr.length - 1) / 2; i >= 0; i--) {
            heapify(arr, i, arr.length);
        }
    }

    public static void heapSort(int[] arr) {
        buildHeap(arr);
        for (int i = arr.length - 1; i >= 0; i--) {
            Tools.swap(arr, 0, i);
            heapify(arr, 0, i);
        }
    }

    public static void main(String[] args) {
        int[] arr = { 5, 6, 8, 3, 2, 1, 9, 7, 2 };
        System.out.println("before sorting:");
        Tools.printArray(arr);
        heapSort(arr);
        System.out.println("after sorting:");
        Tools.printArray(arr);
    }

}

3. 插入排序

 3.1 简单插入排序

整体思路:

第i轮排序,是将第i号元素插入由0,1,2...(i-1)号元素组成的有序表中。

特点:第i轮排序结束后,由0,1,2...i号元素组成的序列是有序的。

时间复杂度:最坏(数组是反序的)O(n^2),平均O(n^2),最好(数组本身就是正序的)O(n)。

空间复杂度:O(1)。

稳定性:稳定。

由于第i个元素之前都是有序的,因此在插入第i个元素的时候,可以从前往后遍历,找到合适的位置就停止。

Java实现:

 1 /**
 2  * @author hr
 3  *
 4  *         以整型数组为例,通过插入排序将数组中的元素按从小到大的顺序进行排列
 5  *         思路:第i轮排序,是将第i号元素插入由0,1,2...(i-1)号元素组成的有序表中
 6  *         特点:第i轮排序结束后,由0,1,2...i号元素组成的序列是有序的
 7  *         时间复杂度:最坏(数组是反序的)O(n^2),平均O(n^2),最好(数组本身就是正序的)O(n)
 8  *         空间复杂度:O(1)
 9  *         稳定性:稳定
10  *         
11  *         由于第i个元素之前都是有序的,因此在插入第i个元素的时候,可以从前往后遍历,
12  *         找到合适的位置就停止
13  */
14 public class InsertionSort {
15     public static void insertionSort(int[] arr) {
16         for (int i = 1; i < arr.length; i++) {
17             int curNum = arr[i];
18             int j;
19             for (j = i - 1; j >= 0 && arr[j] > curNum; j--) {
20                 arr[j + 1] = arr[j];
21             }
22             arr[j + 1] = curNum;
23         }
24     }
25 
26     public static void main(String[] args) {
27         int[] arr = { 5, 6, 8, 3, 2, 1, 9, 7, 2 };
28         System.out.println("before sorting:");
29         Tools.printArray(arr);
30         insertionSort(arr);
31         System.out.println("after sorting:");
32         Tools.printArray(arr);
33     }
34 }

3.2 希尔排序

整体思路:初始将数组均分为gap组,所有下标之差为gap的元素在同一组内,然后对每一组进行插入排序;最后不断调整gap的值进行循环,直到gap为0。 

时间复杂度:最坏O(n^2),平均O(n^1.3),最好O(n)。

空间复杂度:O(1)。

稳定性:不稳定。

实际实现的时候,并不是一组插入排序结束之后再进行另外一组,而是每一组交叉进行。

Java实现:

 1 /**
 2  * @author hr
 3  * 
 4  *         以整型数组为例,通过希尔排序将数组中的元素按从小到大的顺序进行排列 
 5  *         思路:初始将数组均分为gap组,所有下标之差为gap的元素在同一组内,然后对每一组进行插入排序;
 6  *         最后不断调整gap的值进行循环。
 7  *        
 8  *         
 9  *         实际实现的时候,并不是一组插入排序结束之后再进行另外一组,而是每一组交叉进行
10  *         时间复杂度:最坏O(n^2),平均O(n^1.3),最好O(n)
11  *         空间复杂度:O(1)
12  *         稳定性:不稳定
13  *         
14  */
15 
16 public class ShellSort {
17     public static void ShellSort(int[] arr) {
18         for (int gap = arr.length / 2; gap > 0; gap /= 2) {
19             for (int i = gap; i < arr.length; i++) {
20                 for (int j = i - gap; j >= 0; j -= gap) {
21                     if (arr[j] > arr[j + gap]) {
22                         Tools.swap(arr, j, j + gap);
23                     }
24                 }
25             }
26         }
27     }
28 
29     public static void main(String[] args) {
30         int[] arr = { 5, 6, 8, 3, 2, 1, 9, 7, 2 };
31         System.out.println("before sorting:");
32         Tools.printArray(arr);
33         ShellSort(arr);
34         System.out.println("after sorting:");
35         Tools.printArray(arr);
36     }
37 }

4. 归并排序

整体思路:归并排序采用的是分治法。首先不断将数组分为左右两部分,直到每部分都只包含一个元素为止。然后对所有的子序列两两合并,最终得到有序序列。

时间复杂度:最坏O(nlog2n),平均O(nlog2n),最好O(nlog2n)。

空间复杂度:O(n)。

稳定性:稳定。

Java实现:

 1 /**
 2  * @author hr
 3  * 
 4  *         以整型数组为例,通过归并排序将数组中的元素按从小到大的顺序进行排列 
 5  *         思路:归并排序采用的是分治法。首先不断将数组分为左右两部分,直到每部分都只包含一个元素为止。
 6  *         然后对所有的子序列两两合并,最终得到有序序列。
 7  *        
 8  *         时间复杂度:最坏O(nlog2n),平均O(nlog2n),最好O(nlog2n)
 9  *         空间复杂度:O(n)
10  *         稳定性:稳定
11  *         
12  */
13 public class MergeSort {
14     //将arr[first~mid]和arr[mid~last]合并到tmp中
15     public static void mergeArray(int[] arr, int first, int mid, int last) {
16         int[] tmp = new int[last - first + 1];
17         int begin1 = first;
18         int begin2 = mid + 1;
19         int end1 = mid;
20         int end2 = last;
21         int k = 0;
22         while (begin1 <= end1 && begin2 <= end2) {
23             if (arr[begin1] < arr[begin2]) {
24                 tmp[k++] = arr[begin1++];
25             } else {
26                 tmp[k++] = arr[begin2++];
27             }
28         }
29         while (begin1 <= end1) {
30             tmp[k++] = arr[begin1++];
31         }
32         while (begin2 <= end2) {
33             tmp[k++] = arr[begin2++];
34         }
35         //将辅助数组tmp的数据写回arr
36         for (begin1 = 0; begin1 < k; begin1++) {
37             arr[first + begin1] = tmp[begin1];
38         }
39     }
40 
41     public static void mergeSort(int[] arr, int first, int last) {
42         if (last - first > 0) {
43             int mid = (last + first) / 2;
44             mergeSort(arr, first, mid);
45             mergeSort(arr, mid + 1, last);
46             mergeArray(arr, first, mid, last);
47         }
48     }
49 
50     public static void mergeSort(int[] arr) {
51         mergeSort(arr, 0, arr.length - 1);
52     }
53 
54     public static void main(String[] args) {
55         int[] arr = { 5, 6, 8, 3, 2, 1, 9, 7, 2 };
56         System.out.println("before sorting:");
57         Tools.printArray(arr);
58         mergeSort(arr);
59         System.out.println("after sorting:");
60         Tools.printArray(arr);
61     }
62 }

5.计数排序

整体思路:统计出数组中每个元素出现的次数,然后将元素按顺序填入就可得到有序序列。

时间复杂度:三种情况都是O(n + k)。

空间复杂度:O(n + k),k代表数组的宽度。

稳定性:稳定。

在统计每个元素出现的次数时,首先找到数组的宽度(数组最大值和最小值之差再加一),这样,统计数组中的下标就和元素值联系在一起(相差为min)。得到统计值之后,统计数组中的下标可以找到原数组中对应的元素,统计数组的元素值代表原数组对应元素的出现次数

Java实现:

 1 /**
 2  * @author hr
 3  * 
 4  *         以整型数组为例,通过计数排序将数组中的元素按从小到大的顺序进行排列 
 5  *         思路:统计出数组中每个元素出现的次数,然后将元素按顺序填入就可得到有序序列
 6  *         
 7  *         在统计每个元素出现的次数时,首先找到数组的宽度(数组最大值和最小值之差再加一),
 8  *         这样,统计数组中的下标就和元素值联系在一起(相差为min)。得到统计值之后,统计
 9  *         数组中的下标可以找到原数组中对应的元素,统计数组的元素值代表原数组对应元素的出现次数
10  *        
11  *         时间复杂度:三种情况都是O(n + k)
12  *         空间复杂度:O(n + k),k代表数组的宽度
13  *         稳定性:稳定
14  *         
15  */
16 public class CountSort {
17 
18     public static void countSort(int[] arr) {
19         int max = Tools.findMax(arr);
20         int min = Tools.findMin(arr);
21         int[] count = new int[max - min + 1];
22         for (int num : arr) {
23             count[num - min]++;
24         }
25         int index = 0;
26         for (int i = 0; i < count.length; i++) {
27             while (count[i] != 0) {
28                 arr[index++] = i + min;
29                 count[i]--;
30             }
31         }
32     }
33 
34     public static void main(String[] args) {
35         int[] arr = { 5, 6, 8, 3, 2, 1, 9, 7, 2 };
36         System.out.println("before sorting:");
37         Tools.printArray(arr);
38         countSort(arr);
39         System.out.println("after sorting:");
40         Tools.printArray(arr);
41     }
42 }

6. 桶排序

整体思路:根据数组的宽度,生成数量合适的桶。遍历数组,将元素放入对应的桶中。然后对每个桶进行排序,这样,桶内和桶间就都是有序的了。

时间复杂度:最坏:O(n^2),平均:O(n + k),最好:O(n)。

空间复杂度:O(n + k),其中k为数组的宽度。

稳定性:稳定。

实现时,用list<list>代表一个桶,将桶的数量设置为(max - min) / arr.length + 1,这样,(num - min) / arr.length = i的元素就放在第i个桶中。桶内元素我们利用简单插入排序。

Java实现:

 1 /**
 2  * @author hr
 3  *
 4  *         以整型数组为例,通过桶排序将数组中的元素按从小到大的顺序进行排列
 5  *         思路:根据数组的宽度,生成数量合适的桶。遍历数组,将元素放入对应的桶中。然后对每个桶进行排序,
 6  *         这样,桶内和桶间就都是有序的了。
 7  *         
 8  *         实现时,用list<list>代表一个桶,将桶的数量设置为(max - min) / arr.length + 1,这样,
 9  *         (num - min) / arr.length = i的元素就放在第i个桶中。桶内元素我们利用简单插入排序。
10  *          
11  *         时间复杂度:最坏:O(n^2),平均:O(n + k),最好:O(n);
12  *         空间复杂度:O(n + k),其中k为数组的宽度
13  *         稳定性:稳定
14  */
15 public class BucketSort {
16     public static void insertionSort(ArrayList<Integer> bucket) {
17         for (int i = 1; i < bucket.size(); i++) {
18             int j;
19             int curNum = bucket.get(i);
20             for (j = i - 1; j >= 0 && bucket.get(j) > curNum; j--) {
21 
22                 bucket.set(j + 1, bucket.get(j));
23 
24             }
25             bucket.set(j + 1, curNum);
26         }
27     }
28 
29     public static void bucketSort(int[] arr) {
30         int max = Integer.MIN_VALUE;
31         int min = Integer.MAX_VALUE;
32         max = Tools.findMax(arr);
33         min = Tools.findMin(arr);
34         int bucketNum = (max - min) / arr.length + 1;
35         ArrayList<ArrayList<Integer>> buckets = new ArrayList<>();
36         for (int i = 0; i < bucketNum; i++) {
37             buckets.add(new ArrayList<>());
38         }
39 
40         for (int num : arr) {
41             int index = (num - min) / arr.length;
42             buckets.get(index).add(num);
43         }
44 
45         int index = 0;
46         for (int i = 0; i < buckets.size(); i++) {
47             insertionSort(buckets.get(i));
48             for (int num : buckets.get(i)) {
49                 arr[index++] = num;
50             }
51         }
52     }
53 
54     public static void main(String[] args) {
55         int[] arr = { 5, 6, 8, 3, 2, 1, 9, 7, 2 };
56         System.out.println("before sorting:");
57         Tools.printArray(arr);
58         bucketSort(arr);
59         System.out.println("after sorting:");
60         Tools.printArray(arr);
61     }
62 }

7. 基数排序

整体思路:本质上和桶排序是一样的,只是这个桶是固定的10个。排序的过程,就是将所有元素,从个位开始,不断进行桶排序。当所有的数位都排序一遍之后,就得到了有序序列。

时间复杂度:三种情况都是O(n + k)。

空间复杂度:O(n + k),其中k为数组的宽度。

稳定性:稳定。

实现时,可以用list<list>代表一个基数的计数桶;也可以用一个和原数组等长的临时数组,和一个大小为10的计数数组来进行统计。但是用后者会在一次排序的过程中,遍历两遍数组。

Java实现:

 1 /**
 2  * @author hr
 3  *
 4  *         以整型数组为例,通过基数排序将数组中的元素按从小到大的顺序进行排列
 5  *         思路:本质上和桶排序是一样的,只是这个桶是固定的10个。排序的过程,就是将所有元素,从个位开始,
 6  *         不断进行桶排序。当所有的数位都排序一遍之后,就得到了有序序列。
 7  *         
 8  *         实现时,可以用list<list>代表一个基数的计数桶;也可以用一个和原数组等长的临时数组,
 9  *         和一个大小为10的计数数组来进行统计。但是用后者会在一次排序的过程中,遍历两遍数组
10  *          
11  *         时间复杂度:三种情况都是O(n + k);
12  *         空间复杂度:O(n + k),其中k为数组的宽度
13  *         稳定性:稳定
14  */
15 public class RadixSort {
16     public static void radixSort(int[] arr) {
17         ArrayList<ArrayList<Integer>> tmp = new ArrayList<>();
18         for (int i = 0; i < 10; i++) {
19             tmp.add(new ArrayList<>());
20         }
21 
22         int maxNum = Tools.findMax(arr);
23         int maxLength = Integer.toString(maxNum).length();
24 
25         int radix = 1;
26         for (int i = 0; i < maxLength; i++) {
27             for (int k = 0; k < 10; k++) {
28                 tmp.add(new ArrayList<>());
29             }
30 
31             for (int num : arr) {
32                 int digit = (num / radix) % 10;
33                 tmp.get(digit).add(num);
34             }
35 
36             int index = 0;
37             for (int j = 0; j < tmp.size(); j++) {
38                 for (int num : tmp.get(j)) {
39                     arr[index++] = num;
40                 }
41             }
42 
43             radix *= 10;
44             tmp.clear();
45         }
46     }
47 
48     public static void main(String[] args) {
49         int[] arr = { 15, 6, 8, 3, 2, 1, 9, 7, 2 };
50         System.out.println("before sorting:");
51         Tools.printArray(arr);
52         radixSort(arr);
53         System.out.println("after sorting:");
54         Tools.printArray(arr);
55     }
56 }

猜你喜欢

转载自www.cnblogs.com/hrcnblogs/p/9277015.html