基数排序
基数排序算法很特殊,它不需要直接对元素进行相互比较,也不需要将元素相互交换,你需要做的就是对元素进行“分类”。这也是基数排序的魅力所在,基数排序可以理解成是建立在“计数排序”和“桶排序”的基础之上的一种排序算法。在实际项目中,如果对效率有所要求,而不太关心空间的使用时,我会选择用计数排序(当然还有一些其他的条件),或是一些计数排序的变形。
基数排序适合于有不同位数的大小数字,例如以下数列:
核心思想是:
先找十个桶:0~9
第一轮按照元素的个位数排序
桶内分别存放上述数组元素的个位数,按照数组元素的顺序依次存放
之后,按照从左向右,从上到下的顺序依次取出元素,组成新的数组。
在新的数组中,进行第二轮,按照十位数排序,依次存放于桶中:
按照之前的顺序取出,组成新的数组。
进行第三轮,按照百位数排序:
将百位数的元素取出之后,我们发现新的数组已经变成了有序数组
大家也已经发现,排序进行的轮数就是最大数的位数,这几轮进行之后,也就完成了基数排序。
全流程为此图:
算法代码
def radix_sort(li):
max_num = max(li)
it = 0
while 10 ** it <= max_num:
buckets =[[] for _ in range(10)]
for val in li:
i = (val // 10 ** it) % 10
buckets[i].append(val)
# 分桶完成
li.clear()
for buc in buckets:
li.extend(buc)
# 把数据重新写回li
it += 1
算法分析
时间复杂度:O(kn)
空间复杂度:O(k + n)
k 表示数字位数
li = [random.randint(0,10000000000) for _ in range(10000)]
n 表示列表长度
一般情况下:基数排序的算法 比 快速排序(时间复杂度为O(nlogn))快
因为k=log(10,数据) < logn(2,n), 即,k<logn 所以 kn<nlogn
但如果数据比较大时, 即k会增大,基数排序的算法的速度就会降下来可能比快速排序要慢。