Python 基数排序

Posted

技术标签:

【中文标题】Python 基数排序【英文标题】:Python Radix Sort 【发布时间】:2016-02-15 21:15:26 【问题描述】:

我正在尝试在 python 中实现基数排序。

我当前的程序无法正常工作,因为 [41,51,2,3,123] 之类的列表将正确排序为 [2,3,41,51,123],但类似于 [52,41,51,42 ,23] 将变为 [23,41,42,52,51](52 和 51 放错了位置)。

我想我知道为什么会发生这种情况,因为当我比较十位的数字时,我不比较单位(对于 10 的高次幂也是如此)。

如何解决此问题,以便我的程序以最快的方式运行?谢谢!

def radixsort(aList):
    BASEMOD = 10
    terminateLoop = False
    temp = 0
    power = 0
    newList = []
    while not terminateLoop:
        terminateLoop = True
        tempnums = [[] for x in range(BASEMOD)]

        for x in aList:
            temp = int(x / (BASEMOD ** power))
            tempnums[temp % BASEMOD].append(x)
            if terminateLoop:
                terminateLoop = False


        for y in tempnums:
            for x in range(len(y)):
                if int(y[x] / (BASEMOD ** (power+1))) == 0:
                     newList.append(y[x])
                     aList.remove(y[x])



        power += 1

    return newList

print(radixsort([1,4,1,5,5,6,12,52,1,5,51,2,21,415,12,51,2,51,2]))

【问题讨论】:

如果你关心速度,你就不会创建自己的排序。 我正在尝试以最快的速度进行排序 基本上,我不希望它是 O(n^2) 什么的 澄清一下,你意识到你最终不会得到比内置排序更快的排序,对吧? 是的,我并不热衷于速度,但我希望它大约是基数程序的正常时间。 【参考方案1】:

目前,除了最高位之外,您的排序不会对值进行重新排序。你得到4142 只是偶然的(因为它们在初始列表中的相对顺序是正确的)。

您应该始终根据排序的每个循环构建一个新列表。

def radix_sort(nums, base=10):
    result_list = []
    power = 0
    while nums:
        bins = [[] for _ in range(base)]
        for x in nums:
            bins[x // base**power % base].append(x)
        nums = []
        for bin in bins:
            for x in bin:
                if x < base**(power+1):
                    result_list.append(x)
                else:
                    nums.append(x)
         power += 1
     return result_list

请注意,基数排序不一定比基于比较的排序快。如果要排序的项目数大于项目值的范围,则它的复杂性较低。它的复杂度是O(len(nums) * log(max(nums))) 而不是O(len(nums) * log(len(nums)))

【讨论】:

【参考方案2】:

基数排序通过首先对相同位置值的各个数字进行分组来对元素进行排序。 [2,3,41,51,123] 首先我们根据第一位数字对它们进行分组。

[[],[41,51],[2],[3,123],[],[],[],[],[],[]]

然后,根据元素的递增/递减顺序对元素进行排序。新数组将是

[41,51,2,3,123]

然后我们将根据第十位数字进行排序。在这种情况下 [2,3]=[02,03]

[[2,3],[],[123],[],[41],[51],[],[],[],[]]

现在新数组将是

    [2,3,123,41,51] 

最后基于第 100 位数字。这次 [2,3,41,51]=[002,003,041,051]

  [[2,3,41,51],[123],[],[],[],[],[],[],[],[]]

最后我们得到 [2,3,41,51,123]

def radixsort(A):
    if not isinstance(A,list):
        raise TypeError('')
    n=len(A)
    maxelement=max(A)
    digits=len(str(maxelement)) # how many digits in the maxelement
    l=[]
    bins=[l]*10 # [[],[],.........[]] 10 bins
    for i in range(digits):
        for j in range(n): #withing this we traverse unsorted array
            e=int((A[j]/pow(10,i))%10)
            if len(bins[e])>0:
                bins[e].append(A[j]) #adds item to the end
            else:
                bins[e]=[A[j]]
        k=0 # used for the index of resorted arrayA
        for x in range(10):#we traverse the bins and sort the array 
            if len(bins[x])>0:
                for y in range(len(bins[x])):
                    A[k]=bins[x].pop(0) #remove element from the beginning
                    k=k+1
            

【讨论】:

以上是关于Python 基数排序的主要内容,如果未能解决你的问题,请参考以下文章

Python中的基数排序[关闭]

为啥我的基数排序 python 实现比快速排序慢?

python 基数排序

使用python函数进行基数排序

Python中字符串的基数排序

计数排序,桶排序,基数排序的python实现