基数排序 <最低位优先> 链表实现

1.单刀直入

  基数排序是基于多关键字的一种排序,借助“分配”与“收集”两个过程来得到一个有序序列,其时间复杂度为O(d(n+rd)),空间复杂度为O(n+rd),属于稳定的排序...

  举个例子,加入有一下待排序列#->278->109->63->930->589->184->505->269->8->83(#为头节点,其他为数据节点)

  依次序列,我们可以容易得到一下信息:

         rd:rd在这里指的是十进制的十,即rd = 10(but,如果是在一字母序列中,例如#->‘C‘->‘A‘->‘B‘->‘F‘这里rd指的就是二十六进制,即rd = 26)

         d: d在这里指的是序列中最大值的位数,很容易得到此序列中的最大值为930,是一个三位数,即d = 3

2.过程简介

  接上,待排序列为:

  #->278->109->63->930->589->184->505->269->8->83

  接下来,我们就需开始进行第一趟分配(按个位分配),建立是rd个队列或者是rd个链表(以下前面的0,1,2.。。。9都是链表序号):

  注意:按个位分配的意思就是:例如278的个位就是8,就把它放入第8号链表;109的个位是9,就把它放入第9号链表;依次类推。。。

  0->930

  1

  2

  3->63->83

  4->184

  5->505

  6

  7

  8->278->8

  9->109->589->269

  分配后,开始第一趟收集(这里收集就是从0号链表开始收集到9号链表结束):

  #->930->63->83->184->505->278->8->109->589->269

  第二趟分配(按十位分配):

  0->505->109->8

  1

  2

  3->930

  4

  5

  6->63->269

  7->278

  8->83->184->589

  9

  第二趟收集:

  #->505->109->8->930->63->269->278->83->184->589

  第三趟分配(按百位分配):

  0->8->63->83

  1->109->184

  2->269->278

  3

  4

  5->505->589

  6

  7

  8

  9->930

  第三次收集:

  #->8->63->83->109->184->269->278->505->589->930

  排序完成。。。

3.其实思路就是那样,不过代码因人而异,拿什么数据结构去实现就可以达到不同的效果,但结果都可以使之有序,下面给出参考代码

  1 #include <bits/stdc++.h>
  2 #define SIZE 0x32
  3 #define rd 10
  4 using namespace std;
  5 typedef struct snode{
  6     int key;
  7     struct snode* next;//下位指针
  8 } *sRadix;
  9 typedef struct bnode{
 10     sRadix d[SIZE];//最大长度
 11     int length;//实际长度
 12 } bRadix;
 13 int a[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000};//辅助下标数组
 14 int getPos(int value, int pos);//获得下标
 15 void radixSort(bRadix &rl);//基数排序
 16 void printL(bRadix rl);//打印收集链表
 17 void printC(bRadix r);//打印分配过程
 18 int main(){
 19     bRadix rl;//收集主链表
 20     bRadix la;//运动链表
 21     cout << "- - - - - - - - -1.基数排序- - - - - - - - -\n";
 22     cout << "请输入需排序的序列的长度:\n";
 23     cin >> rl.length;
 24     cout << "初始化收集表...";
 25     rl.d[rl.length] = new snode;
 26     rl.d[rl.length]->next = NULL;
 27     la = rl;
 28     cout << "请输入序列的元素集合:\n";
 29     for(int i = 0; i < rl.length; i++){//初始化收集链表
 30         sRadix p = new snode;
 31         cin >> p->key;
 32         p->next = la.d[rl.length]->next;
 33         la.d[rl.length]->next = p;
 34         la.d[rl.length] = p;
 35     }
 36     radixSort(rl);
 37     cout << "进过排序后的序列如下...\n";
 38     printL(rl);
 39     return 0;
 40 }
 41 int getPos(int value, int pos){
 42     return value / a[pos - 1] % 10;
 43 }
 44 void radixSort(bRadix &rl){
 45     int maxValue = 0, d = 1;
 46     bRadix r;
 47     r.length = rl.length;
 48     r.d[r.length] = rl.d[rl.length];
 49     while(r.d[rl.length]->next){
 50         if(r.d[rl.length]->next->key > maxValue)
 51             maxValue = r.d[rl.length]->next->key;
 52         r.d[rl.length] = r.d[rl.length]->next;
 53     }
 54     for(int i = 1; i < rd; i++)
 55         if(maxValue / a[i] == 0) break;
 56         else d++;
 57     for(int i = 1; i <= d; i++){
 58         printf("- - - - - - - - -第%d次分配- - - - - - - - -\n", i);
 59         bRadix r2, r0;
 60         r0.length = r2.length = rl.length;
 61         r0.d[r0.length] = r2.d[r2.length] = rl.d[rl.length];
 62         for(int k = 0; k < rl.length; k++){
 63             r0.d[k] = r2.d[k] = new snode;
 64             r0.d[k]->next = r2.d[k]->next = NULL;
 65         }
 66         while(r0.d[r0.length]->next){
 67             int key = r0.d[rl.length]->next->key;
 68             int pos = getPos(key, i);
 69             for(int j = 0; j < rd; j++){
 70                 if(pos == j){
 71                     sRadix p = new snode;
 72                     p->key = key;
 73                     p->next = r0.d[j]->next;
 74                     r0.d[j]->next = p;
 75                     r0.d[j] = p;
 76                     j = rd;
 77                 }
 78             }
 79             r0.d[r0.length] = r0.d[r0.length]->next;
 80         }
 81         printC(r2);
 82         for(int j = 0; j < rd; j++){
 83             if(r2.d[j]){
 84                 while(r2.d[j]->next){
 85                     int key = r2.d[j]->next->key;
 86                     r2.d[rl.length]->next->key = key;
 87                     r2.d[j] = r2.d[j]->next;
 88                     r2.d[rl.length] = r2.d[rl.length]->next;
 89                 }
 90             }
 91         }
 92     }
 93     cout << "- - - - - - - - -排序结束- - - - - - - - -\n";
 94 }
 95 void printL(bRadix rl){
 96     while(rl.d[rl.length]->next){
 97         cout << rl.d[rl.length]->next->key << " ";
 98         rl.d[rl.length] = rl.d[rl.length]->next;
 99     }
100     cout << endl;
101 }
102 void printC(bRadix r){
103     for(int i = 0; i < rd; i++){
104         printf("#(%d)", i);
105         if(r.d[i]){
106             while(r.d[i]->next){
107                 cout << "->" << r.d[i]->next->key;
108                 r.d[i] = r.d[i]->next;
109             }
110         }
111         cout << endl;
112     }
113 }

效果图如下(包含上述分配与收集过程):

4.没懂的地方请在下边评论区留言,我会尽量为大家解答的。。。希望大家支持

时间: 2024-11-06 10:01:30

基数排序 <最低位优先> 链表实现的相关文章

基数排序(采用链表)

基于两两比较的算法,算法的运行下界为Ω(nlogN),如果想再降低时间复杂度,只能通过其他的非基于比较的方法.基数排序就是一种方法,其时间复杂度为O(N) 基数排序的过程,假设有4个数,我们用链表把他们连一起,这4个数为 321  892   538  439 第一步:我们先创建10个链表,L0~L9,然后按4个数的个位的数字,依次接到相应链表的后面 L0 L1     321 L2     892 L3 L4 L5 L6 L7 L8    538 L9    439 第二步:按连接在链表从L0

排序七:基数排序

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace RadixSort 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 int[] arr = new int[10]; 14 Rand

数据结构基础(二)

二叉树 二叉树的性质 1.非空二叉树上的叶节点数等于双分支节点数加1.2.非空二叉树上第i层上至多有2^(i-1)个节点,这里应有1>=1.3.高度为h的二叉树至多有2^h - 1 个节点 (h>=1).4.在二叉树中,如果所有分支节点都有左孩子和右孩子节点,并且叶子节点都集中在二叉树的最下一层,这样的二叉树称为满二叉树. 只有度为0和度为2的节点 叶子节点都在最下一层 5.完全二叉树:二叉树中最多只有最下面两层的节点的度数可以小于2,并且最下面一层的叶子节点都依次排列在该层最左边的位置上,则

Java实现8中常用的排序

直接插入排序 import java.util.HashMap; /** * 直接插入排序 * @author HHF * 2014年3月19日 */ public class InsertSort { private static int contrastCount = 0;//对比次数 private static int swapCount = 0;//交换次数 public static void main(String[] args) { System.out.println("直接插

桶式排序和基数排序

之前总结了基于比较模型的常见排序算法,它们中最快的也要消耗O(nlogn)时间.但是我们应该知道的是,在一定条件下以线性时间进行排序依然是可能的.桶式排序和基数排序在合适的条件下就是以线性时间执行的算法. 桶式排序(bucket sort): 思想:如果我们限制需要排序的整数的范围,比如说我们有n个整数,范围从0到m-1,我们可以利用这个信息得到一种快速的排序算法.我们留置一个数组,称之为t,大小为m,并初始化为0.于是t有m个单元(桶),开始时它们都是空的.当i被读入时t[i]加一.在所有的输

常见的五类排序算法图解和实现(多关键字排序:基数排序以及各个排序算法的总结)

基数排序思想 完全不同于以前的排序算法,可以说,基数排序也叫做多关键字排序,基数排序是一种借助“多关键字排序”的思想来实现“单关键字排序”的内部排序算法. 两种方式: 1.最高位优先,先按照最高位排成若干子序列,再对子序列按照次高位排序 2.最低位优先:不必分子序列,每次排序全体元素都参与,不比较,而是通过分配+收集的方式. 多关键字排序 例:将下表所示的学生成绩单按数学成绩的等级由高到低排序,数学成绩相同的学生再按英语成绩的高低等级排序.        第一个关键字是数学成绩,第二个关键字是英

内部排序(五)基数排序

基数排序是一种借助多关键字排序的思想对单逻辑关键字进行排序的方法.实现的过程不需要之前的所有排序所需要的记录关键字比较,移动等操作. 多关键字排序: 多关键字排序通常有两种方法: 1.MSD(Most Significant Digit)法,最高为优先法 2.LSD(Least Significant Digit)法,最低位优先法 过程借助分配,收集两种操作. 数组基数排序: 过程演示: 第一步 以LSD为例,假设原来有一串数值如下所示: 73, 22, 93, 43, 55, 14, 28,

数据结构基础(15) --基数排序

基数排序是一种借助"多关键字排序"的思想来实现"单关键字排序"的内部排序算法. 实现多关键字排序通常有两种作法:  最低位优先法(LSD) 先对K[0]{基数的最低位}进行排序,并按 K(0) 的不同值将记录序列分成若干子序列之后,分别对 K[1] 进行排序,..., K[d-1]依次类推,直至最后对最次位关键字排序完成为止.   最高位优先法(MSD) 先对 K[d-1]{基数的最高位}进行排序,然后对 K[d-2]进行排序,依次类推,直至对最主位关键字 K[0]

排序算法(八)——基数排序

基本思想 基数排序(Radix Sort)是在桶排序的基础上发展而来的,两种排序都是分配排序的高级实现.分配排序(Distributive Sort)的基本思想:排序过程无须比较关键字,而是通过"分配"和"收集"过程来实现排序.它们的时间复杂度可达到线性阶:O(n). 先来看一下桶排序(Radix Sort). 桶排序也称为箱排序(Bin Sort),其基本思想是:设置若干个桶,依次扫描待排序的记录R[0],R[1],-,R[n-1],把关键字在某个范围内的记录全都