排序算法——基数排序(C语言)

基数排序的概念:

什么是基数排序???基数排序是一种和快排、归并、希尔等等不一样的排序…它不需要比较和移动就可以完成整型的排序。它是时间复杂度是O(K*N),空间复杂度是O(K+M

基数排序的思想: 

  • 基数排序是一种借助多关键字的思想对单逻辑关键字进行排序的方法。
  • 基数排序根据每个位来分配桶,怎么理解呢???看下面的动图,0-9就是所分配的桶
  • 用大白话来说,基数排序就是先分发数据再回收数据,可以看看下面的动图。

181965eaa5e249518e426b17fcc6d02a.gif

  •  接下来,跟着我的思路走,你也可以实现它。如下面代码,我先定义了一个数组,然后求出来了它的个数。然后就进入基数排序。
int main()
{
	int arr[10] = { 278,109,63,930,589,183,505,269,83,8 };
	int n = sizeof(arr) / sizeof(int);

	for (int i = 0; i < n; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;

	//基数排序
	RadixSrot(arr, 0, n);

	for (int i = 0; i < n; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;

	return 0;
}

 

RadixSort函数实现:

  • 思想就是先分发再回收数据。这里的K,我是用宏来定义的,因为我所创建的arr数组最多也就是到了百位,所以其实我们分发3次数据就可以回收了。
#define K 3
void RadixSrot(int arr[],int left,int right) //[left,right)
{
	for (int i = 0; i < K; i++)
	{
		//分发数据
		Distribute(arr, left, right, i);

		//回收数据
		Collect(arr);
	}
}

分发数据的实现:

  • 分发数据中,我用key来接受了每次分发数据后的值。
  • 下面我来演示它每一次的排序情况。
  • 桶其实就是0-9:
  •  0         1          2        3        4        5         6          7           8            9   
  •  930                         63              505                               278        109
  •                               183                                                        8       589
  •                                  83                                                                269  

然后第一次排序完就是:930  63 183 83 505 278 8 109 589 269

  •  0         1          2        3        4        5         6          7           8            9   
  •   505                         930                         63       278        183
  • 008                                                           269                  083
  • 109                                                                                    589

第二次排序完就是  505   008   109   930   63   269   278   183    038   589

第三次排序完:8   63   83   109   183   269   278   505   589   930

 

  • 它的思想就是这样,也因为它是先分发的数据先回收,所以我定义了10个int的队列,因为考虑最坏情况(如果个位数全部是一样的),得到分发过后的个位数后,我就将数字插入到对应的队列中。然后回收,因为是先分发先回收,队列特性刚好满足,就将队列中的数放到数组中,这就完成了第一次的排序。因为都是百位数,所以最多是3次,就用上面的图中的for循环来完成接下里的排序。

 

#define RADIX 10

//定义基数  构造了10个int的队列
queue<int> Q[RADIX];

void Distribute(int arr[],int left,int right,int k)
{
	
	for (int i = left;i < right; i++)
	{
		int key = GetKey(arr[i], k);
		Q[key].push(arr[i]);
	}

}
int GetKey(int value, int k)
{
	int key = 0;
	while (k >= 0)
	{
		key = value % 10;
		value /= 10;
		k--;
	}

	return key;
}

 

 下面是源码:

#define  _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <queue>
using namespace std;

#define K 3
#define RADIX 10

//定义基数  构造了10个int的队列
queue<int> Q[RADIX];

//value : 278
//k =0 的时候 就得到8  k=1 就得到7
int GetKey(int value, int k)
{
	int key = 0;
	while (k >= 0)
	{
		key = value % 10;
		value /= 10;
		k--;
	}

	return key;
}

//k代表了第几次分发数据
void Distribute(int arr[],int left,int right,int k)
{
	
	for (int i = left;i < right; i++)
	{
		int key = GetKey(arr[i], k);
		Q[key].push(arr[i]);
	}

}

void Collect(int arr[])
{
	int k = 0;
	for (int i = 0; i < RADIX; i++)
	{
		while (!Q[i].empty())
		{
			arr[k++] = Q[i].front();
			Q[i].pop();
		}
	}
}

void RadixSrot(int arr[],int left,int right) //[left,right)
{
	for (int i = 0; i < K; i++)
	{
		//分发数据
		Distribute(arr, left, right, i);

		//回收数据
		Collect(arr);
	}
}

int main()
{
	int arr[10] = { 278,109,63,930,589,183,505,269,83,8 };
	int n = sizeof(arr) / sizeof(int);

	for (int i = 0; i < n; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;

	//基数排序
	RadixSrot(arr, 0, n);

	for (int i = 0; i < n; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;

	return 0;
}

 

 

 

 

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2023年12月26日
下一篇 2023年12月26日

相关推荐