计数排序
计数排序是一种非比较性排序,时间复杂度为O(n + k),主要适用于排序的数组极大值和极小值直接的差不大的情况,如果待排序数组极值差过大,则会造成过多的空间浪费,具体原理如图所示:
-
原理
-
实现
public void countSort(int[] arr) { int min = arr[0], max = arr[0];//获得数组的极值,确定数组长度 for (int i = 1; i < arr.length; i++) { if (min > arr[i]) min = arr[i]; if (max < arr[i]) max = arr[i]; } int[] countArr = new int[max - min + 1]; for (int anArr : arr) countArr[anArr - min]++;//将数据分散到指定的计数桶中 int index = 0;//将技术桶中的数据导入到数组中 for (int i = 0; i < countArr.length; i++) { int count = 0; while (count < countArr[i]) { arr[index] = min + i; index++; count++; } } }
基数排序
基数排序也是一种非比较性排序, 时间复杂度O(K * n),试用场景于计数排序基本一致但是对于空间资源的利用大大提高,基本思路是分别对待排序值的每一位进行排序,比如[15,21,34] 我们首先对个位进行排序,个位排序结果是[21,34,15],之后对十位进行排序得到[15,21,34],由于排序数组最高位就是十位,则完成排序得到最终结果[15,21,34],具体原理如图所示:
-
原理
-
实现
public void radixSort(int[] arr) { Point[] barrel = new Point[10]; int length = getMaxValueLength(arr); //获取循环次数 for (int m = 0; m < length; m++) { for (int i = 0; i < arr.length; i++) { //对数组里每一个数据进行分桶操作 int index = (int) ((arr[i] / (Math.pow(10, m))) % 10); Point p = barrel[index]; if (p == null) barrel[index] = new Point(arr[i], null); else { p.next = new Point(arr[i], p.header); barrel[index] = p.next; } } int i = 0; for (Point point : barrel) { //将本次分桶的结果,保存的数组中 if(point == null) continue; point = point.header; arr[i] = point.val; i++; while((point = point.next) != null) { arr[i] = point.val; i++; } } for (int i1 = 0; i1 < barrel.length; i1++) barrel[i1] = null; } } class Point { int val; Point next; Point header; Point(int val, Point header) { this.val = val; if(header == null){ this.header = this; } else { this.header = header; } } @Override public String toString() { return "Point{" + "val=" + val + ", next=" + next + '}'; } } //获取数组中最大的位数 private int getMaxValueLength(int[] arr) { int max = arr[0]; for (int i : arr) if (i > max) max = i; int length = 1; while ((max /= 10) > 0) length++; return length; }