本文介绍: 基数排序的发明可以追溯到1887年赫尔曼·何乐礼在打孔卡片制表机 (Tabulation Machine)上的贡献。它是这样实现的:将所有待比较数值正整数统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列基数排序方式可以采用LSD(Least significant digital)或MSD(Most significant digital),LSD的排序方式键值的最右边开始,而MSD则相反,由键值

 目录

前言

基数排序

算法思想

​编辑

算法示例

代码实现

1.队列queue.h 头文件

2.队列queue.c 源文件 

 3.主函数(radix_sort实现)

算法分析


前言

        今天我想把前面更新完的排序算法补充一下,也就是基数排序的一种,这是跟计数排序一样类型排序算法,是属于比较型的排序算法,下面我们就一起来看看吧。

基数排序

        基数排序的发明可以追溯到1887年赫尔曼·何乐礼在打孔卡片制表机 (Tabulation Machine)上的贡献。它是这样实现的:将所有待比较数值正整数统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列。 基数排序的方式可以采用LSD(Least significant digital)或MSD(Most significant digital),LSD的排序方式键值的最右边开始,而MSD则相反,由键值的最左边开始。

算法思想

 上面这些理论思想看上去不太好理解,那下面我举个例子简单解释一下。

算法示例

比如有这么一个数组 array = {53, 3, 542, 748, 14, 214, 154, 63, 616}  现在要去进行基数排序。

这里我们需要创建一个长度为10的队列数组。Queue que[10]。然后这个队列数组作为根据基数储存数据队列表。

这里我们数组中的每一个数字去进行遍历然后进行按位求余,最先是个位数,得到的结果,根据对应队列数组下标去进行入队操作。基数分配结果如下所示:

一次基数分配(根据个位数分配

que[0]—–>NULL

que[1]—–>NULL

que[2]—–>542—–>NULL

que[3]—–>53——>3—–>63—–>NULL

que[4]—–>14—–>214—–>154—–>NULL

que[5]—–>NULL

que[6]—–>616—–>NULL

que[7]—–>NULL

que[8]—–>748—–>NULL

que[9]—–>NULL

然后根据第一次基数计算出的结果,重新去排放个数组,对这个队列表进行遍历(从上到下),然后出队操作出队结果放入到数组当中,第一次数组更新结果如下

[ 542, 53, 3, 63, 14, 214, 154, 616, 748 ]

 第二次基数分配(根据十位数分配)

在进行第二次分配的时候我们就根据上面已经跟新好了的数组去重新分配,这一次我们就要去进一位来分配。结果如下:

que[0]—–>3—–>NULL

que[1]—–>14—–>214—–>616—–>NULL

que[2]—–>NULL

que[3]—–>NULL

que[4]—–>542—–>748—–>NULL

que[5]—–>53—–>154—–>NULL

que[6]—–>63—–>NULL

que[7]—–>NULL

que[8]—–>NULL

que[9]—–>NULL

根据第二次基数计算出的结果,重新去排放个数组,对这个队列表进行遍历(从上到下),然后出队操作出队结果放入到数组当中,第二次数组更新结果如下: 

 [ 3, 14, 214 ,616, 542, 748, 53, 154, 63  ]

  第三次基数分配(根据百位数分配)

我们接着取上面第二次分配的数组结果然后再次根据百位数求余数分配。结果如下:

que[0]—–>3—–>14—–>53—–>63—–>NULL

que[1]—–>154—–>NULL

que[2]—–>214—–>NULL

que[3]—–>NULL

que[4]—–>NULL

que[5]—–>542—–>NULL

que[6]—–>616—–>NULL

que[7]—–>748—–>NULL

que[8]—–>NULL

que[9]—–>NULL

 根据第三次基数计算出的结果,重新去排放个数组,对这个队列表进行遍历(从上到下),然后出队操作,出队的结果放入到数组当中第三次数组更新结果如下:

 [ 3, 14, 53, 63, 154, 214, 542, 616, 748 ]

这里我们可以看出,已经拍好序了,但是我建议还是继续去第四次分配,直到全部的数字都在队列que[0]上。 

第四次基数分配(根据千位数分配)

同样的,这里我们把基数再进一位

que[0]—–>3—–>14—–>53—–>63—–>154—–>214—–>542—–>616—–>748—–>NULL

que[1]—–>NULL

que[2]—–>NULL

que[3]—–>NULL

que[4]—–>NULL

que[5]—–>NULL

que[6]—–>NULL

que[7]—–>NULL

que[8]—–>NULL

que[9]—–>NULL

 此时的全部数字都在第一个队列上,这时候就完成了排序,只需要去对这个队列进行出队,然后数据重新放入到数组当中,结果如下,至此,排序结束

  [ 3, 14, 53, 63, 154, 214, 542, 616, 748 ]

 整体分配过程

动态图

代码实现

1.队列queue.h 头文件
#pragma once
#include<stdlib.h>

//数据类型
typedef int Datatype;

//节点
typedef struct node {
	Datatype data;
	struct node* next;
}Lnode;
//队列
typedef struct queue {
	int curnum;
	Lnode* front, * rear;
}Queue;

//队列初始化
void queue_init(Queue* que);
//判空
int isEmpty(Queue q);
//入队列
void enqueue(Queue *que, Datatype data);
//出队列
Lnode* dequeue(Queue* que);
//获取队头元素
Datatype get_headdata(Queue que);
2.队列queue.c 源文件 
#include"queue.h"
#include<assert.h>

//队列初始化
void queue_init(Queue* que) {
	que->curnum = 0;
	que->front = que->rear = NULL;
}

//创建一个节点
Lnode* create_node(Datatype data) {
	Lnode* node = (Lnode*)malloc(sizeof(Lnode));
	assert(node);
	node->data = data;
	node->next = NULL;
	return node;
}

//判空
int isEmpty(Queue q) {
	return q.curnum == 0;
}

//入队列
void enqueue(Queue *que,Datatype data) {
	Lnode* add = create_node(data);
	if (isEmpty(*que)) {
		que->front = que->rear = add;
		que->curnum++;
	}
	else {
		que->rear->next = add;
		que->rear = add;
		que->curnum++;
	}
}

//出队列
Lnode* dequeue(Queue *que) {
	if (isEmpty(*que))
		return NULL;
	if (que->curnum == 1)
		que->rear = NULL;
	Lnode* de = que->front;
	que->front = de->next;
	que->curnum--;
	return de;
}

//获取队头元素
Datatype get_headdata(Queue que) {
	return que.front->data;
}
 3.主函数(radix_sort实现
#include<stdio.h>
#include<stdlib.h>
#include"queue.h"

void radix_sort(int* arr, int n) {
	Queue que[10];//创建下标为0~9的队列
	for (int i = 0; i < 10; i++) {
		queue_init(&amp;que[i]);//初始化队列
	}
	for (int i = 0; i < n; i++) {
		enqueue(&amp;que[arr[i] % 10], arr[i]);//把数组个位数数字依次入队
	}
	int k = 0;
	int count = 10;
	while (que[0].curnum != n) {//如果数字里面全部的数据到第0个队列的时候结束
		for (int i = 0; i < 10; i++) {
			while (!isEmpty(que[i])) {
				Lnode* pop = dequeue(&que[i]);//出队
				arr[k++] = pop->data;//重新放置数组
				//释放空间
				free(pop);
				pop = NULL;
			}
		}

		k = 0;
		
		for (int i = 0; i < n; i++) {
			//除以count取整,此时指向进一位数字,进行入队操作
			int x = arr[i] / count;
			enqueue(&que[x % 10], arr[i]);
		}
		count *= 10;//
	}
}

int main() {
	int array[] = { 123,0, 25,24,6,65,11,43,22,51 ,999 };
	printf("排序前:");
	for (int i = 0; i < sizeof(array) / sizeof(int); i++) {
		printf("%d ", array[i]);
	}
	//基数排序
	radix_sort(array, sizeof(array) / sizeof(int));
	printf("n排序后:");
	for (int i = 0; i < sizeof(array) / sizeof(int); i++) {
		printf("%d ", array[i]);
	}
}

输出结果:

算法分析

以上就是本期的全部内容了,我们下次见咯~

 分享一张壁纸

原文地址:https://blog.csdn.net/m0_73633088/article/details/134613137

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_27762.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注