基数排序

数据结构与算法之美学习笔记:第十三讲

大城市里の小女人 提交于 2019-12-05 00:24:45
一、课前问题 上两节中,我带你着重分析了几种常用排序算法的原理、时间复杂度、空间复杂度、稳定性等。今天,我会讲三种时间复杂度是O(n)的排序算法:桶排序、计数排序、基数排序。 因为这些排序算法的时间复杂度是线性的,所以我们把这类排序算法叫作线性排序(Linear sort)。之所以能做到线性的时间复杂度,主要原因是,这三个算法是非基于比较的排序算法, 都不涉及元素之间的比较操作。 这几种排序算法理解起来都不难,时间、空间复杂度分析起来也很简单,但是对要排序的数据要求很苛刻,所以我们今天 学习重点的是掌握这些排序算法的适用场景 。 按照惯例,我先给你出一道思考题: 如何根据年龄给100万用户排序? 你可能会说,我用上一节课讲的归并、快排就可以搞定啊!是的,它们也可以完成功能,但是时间复杂度最低也是O(nlogn)。有没有更快的排序方法呢?让我们一起进入今天的内容! 二、桶排序(Bucket sort) 1、桶排序的核心思想 首先,我们来看桶排序。桶排序,顾名思义,会用到“桶”,核心思想是将要排序的数据分到一个有序的桶里,每个桶里的数据 再单独进行排序。桶内排完序之后,再把每个桶里的数据按照顺序依次取出,组成的序列就是有序的了。 桶排序的时间复杂度为什么是O(n)呢?我们一块儿来分析一下。 如果要排序的数据有n个,我们把它们均匀地划分到m个桶内,每个桶里就有k=n/m个元素。

Python实现八大排序(基数排序、归并排序、堆排序、简单选择排序、直接插入排序、希尔排序、快速排序、冒泡排序)

蓝咒 提交于 2019-12-04 08:05:07
目录 八大排序 基数排序 归并排序 堆排序 简单选择排序 直接插入排序 希尔排序 快速排序 冒泡排序 时间测试 八大排序 大概了解了一下八大排序,发现排序方法的难易程度相差很多,相应的,他们计算同一列表的时间也不尽相同。今天,我就准备了八种排序的python代码,并且准备测试一下他们计算的时间 基数排序 基数排序的基本思想是先将数字按照个位数上数字的大小进行排序,排序之后再将已经排过序的数字再按照十位数上数字的大小进行排序,依次推类 # 统计这个列表中数字最大的数字有几位 def radix_sort_nums(nums): max = nums[0] for i in nums: if max < i: max = i times = 0 while max > 0: max = int(max/10) times += 1 return times # 每个数字各个位置的数字大小,比如(123,1)则是3,(123,2)则是2 def get_num(num,n): return (int(num/(10**(n-1)))) % 10 # 主程序 def radix_sort(nums): count = 10*[None] # 定义的数组,用于存放当前位数的元素个数 bucket = len(nums)*[None] # 用于暂时存放排序结果 # 分别从个位/十位

基数排序

蓝咒 提交于 2019-12-03 02:24:14
   将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成了一个有序序列。 算法实现: 1 public class radixSort { 2 int a[]={49,38,65,97,76,13,27,49,78,34,12,64,5,4,62,99,98,54,101,56,17,18,23,34,15,35,25,53,51}; 3 public radixSort(){ 4 sort(a); 5 for(inti=0;i<a.length;i++){ 6 System.out.println(a[i]); 7 } 8 } 9 public void sort(int[] array){ 10 //首先确定排序的趟数; 11 int max=array[0]; 12 for(inti=1;i<array.length;i++){ 13 if(array[i]>max){ 14 max=array[i]; 15 } 16 } 17 int time=0; 18 //判断位数; 19 while(max>0){ 20 max/=10; 21 time++; 22 } 23 //建立 10 个队列; 24 List<ArrayList> queue=newArrayList

基数排序

匿名 (未验证) 提交于 2019-12-02 23:40:02
基数排序是一种高效的排序算法,多用于处理字符串(不支持负数,实数排序效率不高) ・ 基数排序就是以每一位的数值为关键字来排序,也就是说,是按位排序(一般从低位向高位枚举) 先贴代码 inline void Qsort (){ for ( int i = 0 ; i < M ;++ i ) b [ i ]= 0 ; // b[i]表示 i 这个数值出现了多少次 for ( int i = 1 ; i <= n ; i ++) b [( a [ i ]/ base )% 10 ]++, rank [ i ]= 0 ; //统计所有数当前位的数值个数 for ( int i = 1 ; i < M ; i ++) b [ i ]+= b [ i - 1 ]; //做前缀和 for ( int i = n ; i >= 1 ; i --) rank [ b [( a [ i ]/ base )% 10 ]--]= a [ i ]; //稍后会讲 for ( int i = 1 ; i <= n ; i ++) a [ i ]= rank [ i ]; //把排好序的数赋给原数组 } inline void sort (){ int max = 0 ; for ( int i = 1 ; i <= n ; i ++) if ( a [ i ]> max ) max = a [ i ]; /

java算法 -- 基数排序

匿名 (未验证) 提交于 2019-12-02 21:40:30
java算法 -- 基数排序 基数排序 (英语:Radix sort)是一种非比较型,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。基数排序的发明可以追溯到1887年在(Tabulation Machine)上的贡献[ 1] 。 它是这样实现的:将所有待比较数值(正整数)统一为同样的数字长度,数字较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。 import java.util.Arrays; public class RadixSort { public int[] sort(int[] sourceArray) throws Exception { // 对 arr 进行拷贝,不改变参数内容 int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); int maxDigit = getMaxDigit(arr); return radixSort(arr, maxDigit); } /** * 获取最高位数 */ private int getMaxDigit(int[] arr) { int maxValue =

基数排序

岁酱吖の 提交于 2019-12-02 00:16:46
基数排序 思想 通过按照键值的各个位的值,把要排序的元素分配到某些桶中,最终实现排序的效果。 将所有待比较的数值统一为同样的数位长度,数位较短的数的前面补充零。 从低位开始依次进行排序,这样从最低位排序到最高位排序完成之后,整个序列就变成了一个有序的序列。 示意图 特点 稳定性排序 基数排序是桶排序的扩展 来源: https://www.cnblogs.com/mengxiaoleng/p/11722684.html

基数排序

心已入冬 提交于 2019-12-01 07:23:36
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int a[120],tmpa[120]; //记录节点 int tong[20],poi[20]; //表示桶和每个位数是i的节点的数量 int n; int MAX(int x,int y) { return x>y?x:y; } int dig(int x) { int num=0; while(x) x/=10,num++; return num; } void Print() { for(int i=0;i<n;i++) cout<<a[i]<<" "; cout<<endl; } void tong_paixu() { int i,j,mx,x,base=1; cin>>n; for(i=0;i<n;i++) cin>>a[i],mx=(i==0?a[0]:MAX(mx,a[i])); int num=dig(mx); while(num--) { memset(tong,0,sizeof(tong)); //每次记录位数是x的数字的数量 for(i=0;i<n;i++) { x=a[i]/base%10; tong[x]++; } memset(poi,0,sizeof(poi)); for(i=1;i<10;i++)

排序算法(第三弹)归并排序和基数(桶)排序

耗尽温柔 提交于 2019-11-30 15:08:50
归并排序 排序动图演示 整体效果: 排序细节: 排序原理: 归并排序就是递归得将原始数组递归对半分隔,直到不能再分(只剩下一个元素)后,开始从最小的数组向上归并排序 1. 向上归并排序的时候,需要一个暂存数组用来排序, 2. 将待合并的两个数组,从第一位开始比较,小的放到暂存数组,指针向后移, 3. 直到一个数组空,这时,不用判断哪个数组空了,直接将两个数组剩下的元素追加到暂存数组里, 4. 再将暂存数组排序后的元素放到原数组里,两个数组合成一个,这一趟结束。 我的代码实现: 1 package cn.ftf.mysort; 2 3 import java.util.Arrays; 4 5 public class MyMergeSort { 6 //完善参数,外部调用 7 public static int[] mergeSort(int[] arr) { 8 int [] temp=new int[arr.length]; 9 arr=mergeSort1(arr,0,arr.length-1,temp); 10 return arr; 11 } 12 //分+治 13 private static int[] mergeSort1(int[] arr,int left,int right,int[] temp) { 14 if(left<right) { 15 int mid

python 十大经典排序算法

只愿长相守 提交于 2019-11-30 03:32:30
python 十大经典排序算法 排序算法可以分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。常见的内部排序算法有:插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。用一张图概括: 关于时间复杂度: 平方阶 (O(n2)) 排序 各类简单排序:直接插入、直接选择和冒泡排序。 线性对数阶 (O(nlog2n)) 排序 快速排序、堆排序和归并排序。 O(n1+§)) 排序,§ 是介于 0 和 1 之间的常数。 希尔排序。 线性阶 (O(n)) 排序 基数排序,此外还有桶、箱排序。 关于稳定性: 稳定的排序算法:冒泡排序、插入排序、归并排序和基数排序。 不是稳定的排序算法:选择排序、快速排序、希尔排序、堆排序。 名词解释: n:数据规模 k:“桶”的个数 In-place:占用常数内存,不占用额外内存 Out-place:占用额外内存 稳定性:排序后 2 个相等键值的顺序和排序之前它们的顺序相同 冒泡排序 冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成

(四)排序——基数排序

久未见 提交于 2019-11-30 02:11:31
基数排序 【思想】基数排序属于“分配式排序”,分为高位优先法MSD和低位优先法LSD 低位优先法LSD: ·从最低位k0开始排序 ·对于排好的序列再用次低位k1排序 ·依次重复,直至对最高位kd-1排好序后,整个序列称为有序的 这是一个分、收;分、收;...;分、收的过程 【特点】稳定 空间复杂度:O(dn) 时间复杂度:基数排序的 时间复杂度 为O (nlog(r)m),其中r为所采取的基数,而m为堆数 注:比其他的稳定 不用比较和移动,采用分配和收集,时间效率高。 基数排序有两种存储方式: 1.基于顺序存储 2.基于链式存储 c++ 该排序实例,是按照桶来放的,在排序过程中用到的桶是二维数组,二维数组前一个数字表示桶号,后一个表示放的位置,降低了理解难度,每个桶内放的个数是用count数组存储,便于从桶内相应位置取出数字。 #include<iostream> using namespace std; int max(int date[],int n){//此函数用于求解所给数组中最大数有几位 int max=0; for(int i=0;i<n;i++){ int count=1,tem=date[i]; while(tem/10!=0){//计算每个数的位数,用count计数 tem=tem/10; count++; } if(count>max) max=count;/