关于排序
1.基数排序
基数排序是按各个元素的每一位上数字的大小依次排序,分为MSD和LSD两种方式,MSD是先排序最高位,然后对结果中被分到同一个组中的数据的下一位继续按位上数字大小继续排序,直到个位排完为止。LSD是先以最低位的数字大小进行排序,接着用第二位进行排序,直到最大元素的最高位排完为止。在这个过程中,可以用数组来作为排序时的桶,先找到数组中桶的分界信息并记录,再按位上数字的大小放入桶中,需要注意的是因为分界的记录是一个分组的左边界相关的,所以要从左向右遍历,以防止将相等的数据交换,造成不稳定,没有心情详细写了,直接放一个测试的程序。
#include <iostream>
#include <malloc.h>
using namespace std;
void printf_array(int array[], int begin, int end);
int get_num(int element, int digit);
int get_MaxDigit(int array[], int begin, int end);
int sort_MsdRadix_(int array[], int begin, int end, int digit);
int sort_MsdRadix(int array[], int array_num);
int sort_LsdRadix_(int array[], int begin, int end, int digit, int *bucket);
int sort_LsdRadix(int array[], int array_num);
int main(void)
{
int test_array[] = {2, 4, 6, 2345, 1, 2, 43, 22, 44, 54};
int num;
num = sizeof(test_array) / sizeof(int);
printf_array(test_array, 0, num - 1);
// sort_MsdRadix(test_array, num);
sort_LsdRadix(test_array, num);
printf_array(test_array, 0, num - 1);
return 0;
}
// 输出数组
void printf_array(int array[], int begin, int end)
{
for (int i = begin; i <= end; i++)
{
cout << array[i] << '\t';
}
cout << endl;
return;
}
/*****************************************
* 功能: 取得一个元素某一位上的数字,即桶号
* 参数:
* element: 元素
* digit: 元素的位,1代表第1位,即个位,2代表第二位,即十位,依次类推
* 返回:
* 元素element第digit位上的数字
*/
int get_num(int element, int digit)
{
for (int i = 2; i <= digit; i++)
{
element = element / 10;
}
return element % 10;
}
/**********************************************************
* 功能: 得到一段数组元素中元素的最大位数
* 参数:
* array: 数组地址
* begin: 起始索引
* end: 末尾索引
* 返回:
* MaxDigit: 最大位数
*/
int get_MaxDigit(int array[], int begin, int end)
{
int MaxDigit = 1;
int MaxVal = array[begin];
for (int i = begin + 1; i <= end; i++)
{
if (array[i] > MaxVal)
{
MaxVal = array[i];
}
}
while (MaxVal >= 10)
{
MaxVal /= 10;
MaxDigit++;
}
return MaxDigit;
}
/************************************************************
* 功能: msd的基数排序,非降序
* 参数:
* array: 数组地址
* begin: 数据的第一个索引
* end: 最后一个索引
* digit: 待排序的数据中最大的位数
* 返回:
* 0
*/
int sort_MsdRadix_(int array[], int begin, int end, int digit)
{
// 首先将原始数据这个大集合分割为一些小的,某一位数字相同的数据的集合,
// 这些集合将全部放在另一个和原始数组大小相同的数组中,另有一个有10个元素的数组用于区分各个集合的边界,
// 按这个边界数组将原始数据重新排列到那个大小相同的数组中,最后将排列好的数据复制回原始数组中去
int *bucket = 0;
int count[10] = {0};
int temp1, temp2;
if ((bucket = (int *)malloc((end - begin + 1) * sizeof(int))) == 0)
{
return -1;
}
for (int i = begin; i <= end; i++)
{
count[get_num(array[i], digit)]++;
}
for (int i = 1; i <= 9; i++)
{
count[i] = count[i] + count[i - 1];
}
for (int i = end; i >= begin; i--)
{
temp1 = get_num(array[i], digit);
bucket[count[temp1] - 1] = array[i];
count[temp1]--;
}
for(int i = begin; i <= end; i++)
{
array[i] = bucket[i - begin];
}
free(bucket);
for (int i = 0; i < 9; i++)
{
temp1 = begin + count[i];
temp2 = count[i + 1] - 1;
if (temp1 < temp2 && digit > 1)
{
sort_MsdRadix_(array, temp1, temp2, digit - 1);
}
}
return 0;
}
/*****************************************************
* 功能: 基数排序,非降序
* 参数:
* array: 数组地址
* array_num: 数组长度
* 返回:
* 0: 成功
* -1: 失败
*/
int sort_MsdRadix(int array[], int array_num)
{
int MaxDigit;
MaxDigit = get_MaxDigit(array, 0, array_num - 1);
return sort_MsdRadix_(array, 0, array_num - 1, MaxDigit);
}
/**************************************************************
* 功能: 按一位上的数字大小进行排列
* 参数:
* array: 数组地址
* begin: 开始索引
* end: 末尾索引
* digit: 对此位排序
* bucket: 辅助空间地址
* 返回:
* 0
*/
int sort_LsdRadix_(int array[], int begin, int end, int digit, int *bucket)
{
// 首先将原始数据这个大集合分割为一些小的,某一位数字相同的数据的集合,
// 这些集合将全部放在另一个和原始数组大小相同的数组中,另有一个有10个元素的数组用于区分各个集合的边界,
// 按这个边界数组将原始数据重新排列到那个大小相同的数组中,最后将排列好的数据复制回原始数组中去
int count[10] = {0};
int temp;
for (int i = begin; i <= end; i++)
{
count[get_num(array[i], digit)]++;
}
for (int i = 1; i <= 9; i++)
{
count[i] = count[i] + count[i - 1];
}
for (int i = end; i >= begin; i--)
{
temp = get_num(array[i], digit);
bucket[count[temp] - 1] = array[i];
count[temp]--;
}
for(int i = begin; i <= end; i++)
{
array[i] = bucket[i - begin];
}
return 0;
}
/**************************************************************
* 功能: lsd基数排序,非降序
* 参数:
* array: 数组地址
* array_num: 数组长度
* 返回:
* 0: 成功
* -1: 失败
*/
int sort_LsdRadix(int array[], int array_num)
{
int MaxDigit;
int *bucket = 0;
if ((bucket = (int *)malloc((array_num)* sizeof(int))) == 0)
{
return -1;
}
MaxDigit = get_MaxDigit(array, 0, array_num - 1);
for (int i = 1; i <= MaxDigit; i++)
{
sort_LsdRadix_(array, 0, array_num - 1, i, bucket) == 1;
}
free(bucket);
return 0;
}