20191209-八大排序之基数排序

1. 基数排序

算法核心思想

基数排序(radix sort)是一种只适用于数字或字母类型的排序方法,它检查数字或字母的每一位,将之分类,按照位数的特定顺序,来将元素排列。以数字为例,将所有元素按照个位数字分类,分类好后,将个位数字大小排列组合起来,再按照十位数字分类,再按照数字大小排列组合起来,一直到最大数位为止。

基数排序分类

基数排序的方式分为2类:

  1. LSD(Least significant digital):LSD的排序方式由键值的最右边开始,先比较最低位,也就是个位,进行分桶,分桶过程中分到一个桶中的数据直接追加到桶中即可,无需排序。然后将所有同种的元素按桶的顺序拿出,重新组成序列,然后比较十位,进行分桶…直到比较到最高位,重新组成序列即可完成排序。
  2. MSD(Most significant digital):由键值的最左边开始,先比较最高位,最高位分到一个桶中的,再按照第二位进行分桶…,知道分到最后一位,然后再从最小的桶中逐层向上,把元素都拿出来,即完成排序。
  3. 首先确定待排序数组中值的最大位数,用于确定程序中要作几轮排序;
  4. 定义一个集合数组,数组大小十,对应角标范围0-9,用来保存每轮排序过程中对应的位数上的值;
  5. 每轮排序依次从原始数组中取值,并判断对应位数上的值,不足位数时在前面补上相应的0,然后放到对应角标的桶内;
  6. 每轮排序后,按角标大小依次取出不为空的桶内的值,合并成为一个部分排序后的新数组;
  7. 将上述部分排序后的新数组作为下一轮高一位位数上的值排序的原始数组,重复上述排序的步骤,直到生成最终排好序的数组。

LSD具体逻辑如下:

MSD具体逻辑如下:

从最高位数上的值开始排序,一轮排序结束后,并没有急着合并整理,而是判断每个桶内的元素,如果桶内的元素大于1个则继续对当前桶进行排序,直到排到最低位数上的值,最终做一次性合并整理,形成排序后的数组。

代码实现-数字LSD算法

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 arr

代码实现-数字MSD算法

def 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 arr

代码实现-字母LSD算法

def 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个函数,一个函数是获取字母应该放置到哪个桶中,一个函数根据获取的桶的索引将元素放置入桶中

代码实现-字母MSD算法

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 arr

执行解析

总结

LSD从低位开始排到高位,每排一位都是把各个桶合并,再按下一位排序;
MSD从高位开始排到低位,排完一位后不合并桶,相同的高位划分子桶继续分配,最后再合并。

堆排序本身没有普适性,仅能用于特定的数组排序,如字母和数字的排序。

原文地址:https://www.cnblogs.com/hyj691001/p/12013413.html

时间: 2024-11-08 21:26:52

20191209-八大排序之基数排序的相关文章

八大排序算法

转载:http://blog.csdn.net/hguisu/article/details/7776068 目录(?)[+] 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 我们这里说说八大排序就是内部排序. 当n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序.堆排序或归并排序序. 快速排序:是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速

谈谈八大排序算法问题

排序算法可以说是算法的入门以及算法学习阶段的基石,排序算法显得那么的基础又是非常重要的一种算法.排序算法常常作为一些高阶算法的数据处理中间过程在实际的问题处理中被应用的最为广泛,因此算法选将阶段就从八大排序算法开始.在本节内容中既可以看到一般性的比如插入排序,冒泡排序等基础算法又可以看到比如基数排序,位图排序,快速排序等等比较难理解的算法,算法之门从排序算法说起. 1.插入排序 插入排序算法的原理很简单,默认A中有一部分数据已经排好序了,后续只要从没有排好序的序列里面每拿出一个数字就在排好序的序

数据结构与算法之——八大排序算法

附:关于这个主题,网上好的文章已经数不胜数,本篇是整合后的文章. 正文: 一.概述 排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 本文所指八大排序就是内部排序. 当n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序.堆排序或归并排序序. 快速排序:是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短: 二.排序算法详述 1.

八大排序算法总结及C/C++实现

概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 我们这里说说八大排序就是内部排序. 当n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序.堆排序或归并排序. 快速排序:是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短: 1. 插入排序-直接插入排序(Straight Insertion Sort) 基本思想: 将一个记录插入到

[Data Structure] 八大排序算法

排序有内部排序和外部排序之分,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存.我们这里说的八大排序算法均为内部排序. 下图为排序算法体系结构图: 1. 直接插入排序(Straight Insertion Sort ) 基本思想:将待排序的无序数列看成是一个仅含有一个元素的有序数列和一个无序数列,将无序数列中的元素逐次插入到有序数列中,从而获得最终的有序数列. 算法流程: 1)初始时, a[0]自成一个有序区, 无序区为a[1

(转)详解八大排序算法

概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 我们这里说说八大排序就是内部排序. 当n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序.堆排序或归并排序序. 快速排序:是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短: 1.插入排序—直接插入排序(Straight Insertion Sort) 基本思想: 将一个记录插入到

Python学习(三) 八大排序算法的实现(下)

本文Python实现了插入排序.基数排序.希尔排序.冒泡排序.高速排序.直接选择排序.堆排序.归并排序的后面四种. 上篇:Python学习(三) 八大排序算法的实现(上) 1.高速排序 描写叙述 通过一趟排序将要排序的数据切割成独立的两部分,当中一部分的全部数据都比另外一部分的全部数据都要小,然后再按此方法对这两部分数据分别进行高速排序,整个排序过程能够递归进行,以此达到整个数据变成有序序列. 1.先从数列中取出一个数作为基准数. 2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全

八大排序算法Java(转)

目录(?)[-] 概述 插入排序直接插入排序Straight Insertion Sort 插入排序希尔排序Shells Sort 选择排序简单选择排序Simple Selection Sort 选择排序堆排序Heap Sort 交换排序冒泡排序Bubble Sort 交换排序快速排序Quick Sort 归并排序Merge Sort 桶排序基数排序Radix Sort 总结 概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序

(转)八大排序对比

排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 我们这里说说八大排序就是内部排序. 当n较大,则应采用时间复杂度为O(nlog2n)的排序方法:快速排序.堆排序或归并排序序. 快速排序:是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短: 1.插入排序—直接插入排序(Straight Insertion Sort) 基本思想: 将一个记录插入到已排序

排序算法(九)——八大排序算法总结

八大排序算法的稳定性及复杂度总结如下: 选择排序算法准则 每种排序算法都各有优缺点.因此,在实用时需根据不同情况适当选用,甚至可以将多种方法结合起来使用. 影响排序的因素有很多,平均时间复杂度低的算法并不一定就是最优的.相反,有时平均时间复杂度高的算法可能更适合某些特殊情况.同时,选择算法时还得考虑它的可读性,以利于软件的维护.一般而言,需要考虑的因素有以下四点: 1.待排序的记录数目n的大小: 2.记录本身数据量的大小,也就是记录中除关键字外的其他信息量的大小: 3.关键字的结构及其分布情况: