wuxiaosi0 2019-12-09
基数排序(radix sort)是一种只适用于数字或字母类型的排序方法,它检查数字或字母的每一位,将之分类,按照位数的特定顺序,来将元素排列。以数字为例,将所有元素按照个位数字分类,分类好后,将个位数字大小排列组合起来,再按照十位数字分类,再按照数字大小排列组合起来,一直到最大数位为止。
基数排序的方式分为2类:
从最高位数上的值开始排序,一轮排序结束后,并没有急着合并整理,而是判断每个桶内的元素,如果桶内的元素大于1个则继续对当前桶进行排序,直到排到最低位数上的值,最终做一次性合并整理,形成排序后的数组。
def BucketSort(arr):
    max_num = max(arr)
    i = 0
    #(max_num//10**i)%10>0表示当数组中最大的数的最高位没有进行排序前,都一直循环
    while (max_num//10**i)%10>0:
        buckets = [[] for i in range(10)]
        for num in arr:
            # (num//10**i)%10获取当前排序的基准数(对应的桶号),如取320的第二个数,则需要放置在2号桶中
            bucketIndex = (num//10**i)%10
            buckets[bucketIndex].append(num)
        arr =[]
        #将桶中的数组从新组合为一个新的数组
        for bucket in buckets:
            arr+=bucket
        i +=1
    return arrdef BucketSortMsd(arr,max_length):
    if max_length<=0:
        return arr
    print("对于当前数组%s按照右起第%s位数排序"%(arr,max_length))
    buckets = [[] for i in range(10)]
    for num in arr:
        #num // 10 ** (max_length - 1) % 10 ** (max_length) 获取当前数字的桶index
        bucket_idx = num//10**(max_length-1)%10**(max_length)
        buckets[bucket_idx].append(num)
    arr = []
    for bucket in buckets:
        if len(bucket)>2:
            arr+=BucketSortMsd(bucket,max_length-1)
        else:
            arr+=bucket
    return arrdef BucketSortLetterLsd(arr):
    sort_arround = len(max(arr))
    while sort_arround>=0:
        buckets = [[] for i in range(26)]
        for letter in arr:
            if sort_arround>=len(letter):
                bucket_index = 0
            else:
                bucket_index = ord(letter[sort_arround])-97
            buckets[bucket_index].append(letter)
        arr = []
        for bucket in buckets:
            arr+=bucket
        sort_arround-=1
    return arr
arr = ["banana","apple","orange","ape","he"]
print(BucketSortLetterLsd(arr))根据计算出的桶的索引放置单词,并且放置后按照桶的位置从0-26逐一取出桶中的单词放回序列,然后进行下一轮排序,一直到排序完最后一轮。
1. 不管待排列表是多少个元素,以及元素的长度为多少,都需要创建27个桶,分别对应其他字符以及a-z的26个英文字母
2. 获取待排元素的的最长的单词作为排序的轮数
3. 从低位到高位依次排序(注意:一定是要从地位到高位才能完成我们的字典序)
具体代码分为2个函数,一个函数是获取字母应该放置到哪个桶中,一个函数根据获取的桶的索引将元素放置入桶中
def LetterBucketSortMsd(arr,sort_idx):
    """sort_idx表示按照给定arr中数组中字母的第几个索引进行排序"""
    # 如果排序的字母位索引超出最大长度,直接返回数组,如对字母abc按照下标3第4个字母进行排序,这种情况无需排序,直接返回
    if sort_idx>len(max(arr)):
        return arr
    #建立26个桶
    buckets = [[] for i in range(26)]
    for letter in arr:
        if len(letter)>sort_idx:
            #获取桶的索引
            bucket_index = ord(letter[sort_idx])-97
        else:
            bucket_index = 0
        buckets[bucket_index].append(letter)
    arr = []
    for bucket in buckets:
        #如果桶中的元素超过2个,则继续排序,最后合并桶
        if len(bucket)>=2:
            arr+=LetterBucketSortMsd(bucket,sort_idx-1)
        else:
            arr+=bucket
    return arrLSD从低位开始排到高位,每排一位都是把各个桶合并,再按下一位排序;
MSD从高位开始排到低位,排完一位后不合并桶,相同的高位划分子桶继续分配,最后再合并。
堆排序本身没有普适性,仅能用于特定的数组排序,如字母和数字的排序。