【数据结构】基数排序

本文深入探讨了基数排序算法,这是一种非比较型整数排序算法,特别适合处理包含不同位数的数字。核心思想是通过分配和收集步骤,按照数字的每一位进行排序。文章提供了详细的步骤解析及C++代码实现,展示了如何通过多轮处理完成排序,最终得到有序数组。
摘要由CSDN通过智能技术生成

内容描述

基数排序适合于有不同位数的大小数字,例如以下数列:
在这里插入图片描述
核心思想是:
先找十个桶:0~9
第一轮按照元素的个位数排序
桶内分别存放上述数组元素的个位数,按照数组元素的顺序依次存放
在这里插入图片描述
之后,按照从左向右,从上到下的顺序依次取出元素,组成新的数组。
在这里插入图片描述
在新的数组中,进行第二轮,按照十位数排序,依次存放于桶中:
在这里插入图片描述
按照之前的顺序取出,组成新的数组。
进行第三轮,按照百位数排序:
在这里插入图片描述
将百位数的元素取出之后,我们发现新的数组已经变成了有序数组
在这里插入图片描述
大家也已经发现,排序进行的轮数就是最大数的位数,这几轮进行之后,也就完成了基数排序。

全流程为此图:
在这里插入图片描述

代码实现

#include <iostream>
#define MAXNUM_KEY 8                //关键字项数的最大值 
#define RADIX 10                    //关键字基数,此时是十进制整数的基数 
#define MAX_SPACE 10000 
using namespace std;

typedef struct                       // 结点类型 
{ 
	char keys[MAXNUM_KEY];           //关键字 
  	int next;                       // 后继结点的下标 
}SLCell;
typedef struct
{ 
  	SLCell r[MAX_SPACE];                //静态链表的可利用空间,r[0]为头结点 
  	int keynum;                        //记录的当前关键字个数,即元素的最大长度 
  	int recnum;                       //静态链表的当前长度 
}SLList;                           //静态链表类型 

void InitList(SLList *L)
{ 
  	int i,n,keynum;     
  	cin>>n>>keynum;
  	(*L).keynum=keynum;
  	(*L).recnum=n;
  	for(i=1;i<=n;i++)
    	cin>>(*L).r[i].keys;
}

void Distribute(SLCell *r,int i,int *f,int *e)     // 分发函数(将元素按当前位的大小分组) 
{ 
  	int j,p; 
  	for(j=0;j<RADIX;++j)  f[j]=0; 
    for(p=r[0].next;p;p=r[p].next)
    { 
    	j=r[p].keys[i]-'0';                  // 当前位的大小 
    	if(!f[j])                            
    		f[j]=p;                        // 若为 0,则赋为该分组的头结点 
   		else  
    	    r[e[j]].next=p;              // 若头结点已有,则以尾插法插入 
    	e[j]=p;                         // e[j]用于记录该分组的尾结点,更新尾结点 
   	}
} 

void Collect (SLCell *r,int i,int *f,int *e)    // 集合函数,将分组后的每一组元素首尾相接 
{ 
  	int j,t;
  	for(j=0;!f[j];j++);                      // 找到第一组 
  	r[0].next=f[j];                         // r[0]为头结点 
  	t=e[j];                                // 记录当前分组的尾结点 
  	while(j<RADIX-1)
  	{ 
    	for(j++;j<RADIX-1&&!f[j];j++) ; // 找到下一组 
      	if(f[j]) 
      	{
       		r[t].next=f[j];          // 首尾相接 
       		t=e[j];                 // 更新尾结点 
      	}
  	} 
  	r[t].next=0;  
} 

void RadixSort(SLList &L)
{ 
   	int i;
   	int f[RADIX],e[RADIX];                     // f[RADIX]记录头结点,e[RADIX]记录尾结点 
   	for(i=0;i<L.recnum;++i)  L.r[i].next=i+1; // 下标初始化 
   	L.r[L.recnum].next = 0; 
   	for(i=L.keynum-1;i>=0;i--) 
   	{           
    	Distribute(L.r,i,f,e); 
     	Collect(L.r,i,f,e);    
   	}
}

void print(SLList L)
{  
  	int p,flag=1;
  	for(p=L.r[0].next;p;p=L.r[p].next)
  	{
	  	if(flag)
   		{cout<<L.r[p].keys;flag=0;}
   		else
    	cout<<" "<<L.r[p].keys;
   	}
}

int main()
{
  	SLList l;
  	InitList(&l);
  	RadixSort(l);
  	print(l);
  	return 0;
} 

参考:

八种排序算法之七:图解基数排序_Guo_ping’blog-CSDN博客_基数排序

基数排序是一种非比较排序算法,它根据数据元素的每个位上的值进行排序。下面是基于顺序队列的基数排序的C语言实现: ```c #include <stdio.h> #include <stdlib.h> // 定义数据元素的数据结构 typedef struct { int key; } DataType; // 定义队列的数据结构 typedef struct { DataType *data; int front; int rear; } Queue; // 初始化队列 void initQueue(Queue *queue, int size) { queue->data = (DataType *)malloc(size * sizeof(DataType)); queue->front = queue->rear = 0; } // 入队操作 void enqueue(Queue *queue, DataType element) { queue->data[queue->rear++] = element; } // 出队操作 DataType dequeue(Queue *queue) { return queue->data[queue->front++]; } // 判断队列是否为空 int isEmpty(Queue *queue) { return queue->front == queue->rear; } // 获取关键字的某一位上的值 int getDigit(int number, int digit) { int i; for (i = 0; i < digit - 1; i++) { number /= 10; } return number % 10; } // 基数排序 void radixSort(DataType *data, int size, int digit) { int i, j, k; Queue *queues = (Queue *)malloc(10 * sizeof(Queue)); // 创建10个队列,用于存放每个位上的数据元素 // 初始化队列 for (i = 0; i < 10; i++) { initQueue(&queues[i], size); } // 根据每个位上的值将数据元素入队 for (i = 1; i <= digit; i++) { for (j = 0; j < size; j++) { int digitValue = getDigit(data[j].key, i); enqueue(&queues[digitValue], data[j]); } // 将队列中的数据元素按顺序出队,更新原数组 k = 0; for (j = 0; j < 10; j++) { while (!isEmpty(&queues[j])) { data[k++] = dequeue(&queues[j]); } } } // 释放队列的内存空间 for (i = 0; i < 10; i++) { free(queues[i].data); } free(queues); } int main() { int size = 10; int digit = 3; DataType data[] = {{710}, {342}, {45}, {686}, {6}, {841}, {429}, {134}, {68}, {264}}; radixSort(data, size, digit); // 输出排序结果 for (int i = 0; i < size; i++) { printf("%d ", data[i].key); } printf("\n"); return 0; } ``` 运行以上代码,输出结果为:6 45 68 134 264 342 429 686 710 841
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赤城封雪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值