排序可以分为俩种: 基于比较的排序和不基于比较的排序(根据数据的状况。。。。)
申请额外的数组进行 频率统计。 根据数据的大小, 分配大小。
词频 统计
计数排序:统计词频
基数排序:根据个位数,十位数,百位数,放。要排序的对象 要有进制。
根据个位数放。放完之后,倒出来,同一个桶的数据先进先出
然后根据十位数放。一样
入桶出桶的次数和最大值有关。
计数排序
要了解数据的情况,最大值,最小值。
public void userSort(int[] arr) {
if (arr == null || arr.length < 2) {
return;
}
// max 代表当前数组里的最大数
int max = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
max = Math.max(max, arr[i]);
}
int[] bucket = new int[max + 1]; // 辅助数组,size = max + 1
// 遍历原始数组,构造辅助数组。
for (int i = 0; i < arr.length; i++) {
bucket[arr[i]]++; // 当前值 的下标在辅助数组 累积+1
}
// 遍历辅助数组,依次打印,
int index = 0; // 原数组下标 变量,依次递增
for (int i = 0; i < bucket.length; i++) {
while (bucket[i] > 0) {
arr[index] = i;
index++;
bucket[i]--;
}
}
python 实现
def user_sort(self, arr):
import sys
max_num = -sys.maxsize - 1
for item in arr:
max_num = max(max_num, item)
bucket = []
for i in range(2*max_num + 1):
bucket.append(0)
for item in arr:
bucket[item] += 1
index = 0
for i,item in enumerate(bucket):
while item > 0:
arr[index] = i
index +=1
item -= 1
基数排序
@Override
public void userSort(int[] arr) {
// 数 都是非负数
int jiweishu = maxbits(arr);
radixSort(arr, 0, arr.length - 1, maxbits(arr));
}
public static int maxbits(int[] arr) {
// 获取当前数组最大的数 是几位。
int max = Integer.MIN_VALUE;
for (int i = 0; i < arr.length; i++) {
max = Math.max(max, arr[i]);
}
int res = 0;
while (max != 0) {
res++;
max /= 10;
}
return res;
}
public static int getDigit(int x, int d) {
return ((x / ((int) Math.pow(10, d - 1))) % 10);
}
public static void radixSort(int[] arr, int l, int r, int digit) {
int radix = 10; // 十进制的数
int i = 0;
int j = 0;
int[] bucket = new int[r - l + 1]; // 辅助数组,和原数组等规模
// 外层for循环控制 进出桶的次数,从个位开始,最大数是三位数,就进出桶三次
for (int d = 1; d <= digit; d++) {
// d代表当前位, 个位还是十位还是百位
// 值代表当前位 的 词频
int[] count = new int[radix]; // 桶 0, 1, 2, 3, 4,5, 6, 7 , 8 ,9
// 进桶
for (i = l; i <= r; i++) {
j = getDigit(arr[i], d);
count[j]++;
}
// 加工一下,词频数组count 变为前缀和,以前是个位数字i == value 的个数,现在是 i <= value 的个数
for (i = 1; i < radix; i++) {
count[i] = count[i] + count[i - 1];
}
// 从右往左(先入桶的先出), 比如 <= 2 的数有4个。 出桶
for (i = r; i >= l; i--) {
j = getDigit(arr[i], d);
bucket[count[j] - 1] = arr[i]; // 当前值应该放在辅助数组的哪个位置。
count[j]--; // 当前值前缀和 -1,后面的不管,各自使用各自的片
}
// 辅助数组 复制 回 原数组
for (i = l, j = 0; i <= r; i++, j++) {
arr[i] = bucket[j];
}
}
}
python 实现
class RadixSort(ArrayUtil):
def user_sort(self, arr):
radix = 10
bucket = [ 0 for x in range(len(arr))]
max_d = self.get_max_digit(arr)
for d in range(1, max_d + 1):
count = [0 for x in range(radix)]
for item in arr:
cur_d = self.get_digit(item, d)
count[cur_d] += 1
for index in range(1, radix):
count[index] = count[index] + count[index-1]
for item in arr[::-1]:
cur_d = self.get_digit(item, d)
bucket[count[cur_d] - 1 ] = item
count[cur_d] -= 1
for index, item in enumerate(bucket):
arr[index] = item
def get_max_digit(self, arr):
import sys
max_num = -sys.maxsize - 1
for item in arr:
max_num = max(max_num, item)
res = 0
while max_num != 0:
res += 1
max_num = max_num /10
return res
def get_digit(self, num, d):
# 获取一个数的第几位,数
tmp_10_pow = pow(10, d - 1)
return int((num / (tmp_10_pow)) % 10 )
边界值一定要思考。不急慢慢来