基數排序法
来源:互联网 发布:als算法 与svd 编辑:程序博客网 时间:2024/04/30 14:53
http://openhome.cc/Gossip/AlgorithmGossip/RadixSort.htm
說明
在之前所介紹過的排序方法,都是屬於「比較性」的排序法,也就是每次排序時 ,都是比較整個鍵值的大小以進行排序。這邊所要介紹的「基數排序法」(radix sort)則是屬於「分配式排序」(distributionsort),基數排序法會使用到「桶子」(bucket),顧名思義,它是透過鍵值的部份資訊,將要排序的元素分配至某些「桶」中,藉以達到排序的作用,基數排序法是屬於穩定性的排序,其時間複雜度為O(nlog(r)m),其中r為所採取的基數,而m為堆數,在某些時候,基數排序法的效率高於其它的比較性排序法。
解法
基數排序的方式可以採用LSD(Least sgnificant digital)或MSD(Most sgnificant digital),LSD的排序方式由鍵值的最右邊開始,而MSD則相反,由鍵值的最左邊開始。以LSD為例,假設原來有一串數值如下所示:
首先根據個位數的數值,在走訪數值時將它們分配至編號0到9的桶子中:
0 1 2 3 4 5 6 7 8 9
81
65
39
43 14 55
28
93
22 73
接下來將這些桶子中的數值重新串接起來,成為以下的數列:
接著再進行一次分配,這次是根據十位數來分配:
0 1 2 3 4 5 6 7 8 9
2839
14 22
43 55 65 73 81 93
接下來將這些桶子中的數值重新串接起來,成為以下的數列:
這時候整個數列已經排序完畢;如果排序的對象有三位數以上,則持續進行以上的動作直至最高位數為止。
LSD的基數排序適用於位數小的數列,如果位數多的話,使用MSD的效率會比較好,MSD的方式恰與LSD相反,是由高位數為基底開始進行分配,其他的演算方式則都相同。
原文有作者自己写的各种语言的代码
这里我改写了下作者写的c代码
#include <string.h>#include <stdlib.h>#include <stdio.h>#include <math.h>#include <time.h>#include <vector>using namespace std;void swap(int &a,int&b){int tmp = a;a = b;b = tmp;}void radix_sort(int *array,int number_of_data,int length){int counter = 0;int n =1;while (counter<number_of_data){int counter_for_index[10] = {0};//桶中的计数器 表示放了多少个元素int tmp[10][10] = {0};//将数据放入对应的桶中for (int i = 0;i<length;i++){int index = (array[i]/n)%10;tmp[index][counter_for_index[index]++] = array[i];}n*=10;counter++;//位数计数器//将放入桶中的数据写入原数组int k = 0;for (int i= 0;i<10;i++){for (int j = 0;j<counter_for_index[i];j++){array[k++] = tmp[i][j];}}}}void main(){int a[] = {111,2,9,67,3,5,6,6,7,8};radix_sort(a,3,sizeof(a)/sizeof(int));for (int i = 0;i<sizeof(a)/sizeof(int);i++){printf("%d ",a[i]);}printf("\n");getchar();}
下面是用队列和向量实现的MSD
from http://angels1.0.blog.163.com/blog/static/8458050420099294956971/
采用MSD过程如下:
第一次: 所有元素按照百位排序
0 号:059
1 号:179
2 号:232
3 号:332 361
4 号:457 405
5 号:589
6 号:633 644
7 号:714
8 号:825
9 号:
形成序列: 059 179 232 332 361 457 405 589 633 644 714 825 (已经基本有序)
第二次:桶内元素按照十位排序
从上面的可以看出只有3号4号和6号需要继续进行排序:
3号桶中 4号桶中 6号桶中
0 号: 0 号: 405 0 号:
1 号: 1 号: 1 号:
2 号: 2 号: 2 号:
3 号:332 3 号: 3 号: 633
4 号: 4 号: 4 号:
5 号: 5 号:457 5 号:
6 号:361 6 号: 6 号: 644
7 号: 7 号: 7 号:
8 号: 8 号: 8 号:
9 号: 9 号: 9 号:
形成序列: 059 179 232 332 361 405 457 589 633 644 714 825 (其实已经有序了)
第三次:按照各位对各个桶元素排序:
由于各个桶内只剩下一个元素或没有元素,下面的就不再写了
#include <string.h>#include <stdlib.h>#include <stdio.h>#include <math.h>#include <time.h>#include <vector>#include <queue>using namespace std;//dem从0开始计算 获得num的第dem位int getradix(int num,int dem){while (dem--){num/=10;}return (num % 10);}//dem表示数据的从0开始 如果是两位数 数据最多占据0 1 位置dem初始为1void radix_sort(vector<int>&data,int dem ){if (data.empty()||dem<0){return ;}vector<queue<int>> buckets(10);//将元素放入桶中for (int i = 0;i<data.size();i++){int index = getradix(data[i],dem);buckets[index].push(data[i]);}//桶中的元素其实放在队列中存储的 所以先将队列中的元素放入向量中for (int i = 0;i<10;i++){//当元素个数大于1时 进行排序if (buckets[i].size()>1){vector<int> tmp;//将桶中的元素放入向量tmp中while (!buckets[i].empty()){tmp.push_back(buckets[i].front());buckets[i].pop();}//递归进行排序 按dem-1位排序 radix_sort(tmp,dem-1);//将排好序的元素放入对于的桶中for (int j = 0;j<tmp.size();j++){buckets[i].push(tmp[j]);}}// if num of elem in bucket is big than 1,sort}//for every bucket//将桶中排好序的元素写入原向量中int data_index = 0;for (int i = 0;i<10;i++){while (!buckets[i].empty()){data[data_index++] = buckets[i].front();buckets[i].pop();}}}void main(){vector<int> a;srand(time(NULL));for (int i = 0;i<600;i++){a.push_back(rand()%100);}radix_sort(a,1);for (int i = 0;i<a.size();i++){printf("%d ",a[i]);}printf("\n");getchar();}
- 基數排序法
- 基數排序法
- 排序--快速排序法
- 【排序】快速排序法
- 【排序】冒泡排序法
- 【排序】插入排序法
- 【排序】归并排序法
- 【排序】堆排序法
- 【排序】希尔排序法
- 快速排序法排序
- 排序:起泡排序法
- 数据结构-排序: 交换排序(冒泡排序法)
- 数据结构-排序: 交换排序(快速排序法)
- 数据结构-排序: 交换排序(快速排序法)
- 数据结构-排序: 交换排序(冒泡排序法)
- 选择法排序,冒泡排序,递归排序
- 排序法
- 排序法
- 使用SQLite储存数据
- 【cocos2d-x官方文档】动画 Animations
- Oracle 字符集的查看和修改
- Oracle中的character set 和 national character set
- Java菜鸟学习笔记--配置篇(三):Java API 文档下载与文档注释的使用
- 基數排序法
- WCF配置故障
- Java04 save and read the .txt
- ABAP查询Table方法
- TUN/TAP
- 将dataset中的数据导出至Excel中而不需要安装MS Excel的方法(含UNICODE支持)
- 汽水瓶
- bebug assertion failed问题解决
- linux下实现虚拟网卡TAP/TUN例子