using System;
public class Program
{
public static void Main(string[] args)
{
double[] array = { 0.43, 0.69, 0.11, 0.72, 0.28, 0.21, 0.56, 0.80, 0.48, 0.94, 0.32, 0.08 };
BucketSort(array);
ShowSord(array);
Console.ReadKey();
}
private static void ShowSord(double[] array)
{
foreach (var num in array)
{
Console.Write($"{num} ");
}
Console.WriteLine();
}
public static void BucketSort(double[] array, int bucketNum=10)//最多就10个桶 因为是十进制只有10个数
{
//创建bucket时,在二维中增加一组标识位,其中bucket[x, 0]表示这一维所包含的数字的个数
//通过这样的技巧可以少写很多代码
double[,] bucket = new double[bucketNum, array.Length + 1];//其实这样有点浪费空间 用list 可能更好 空间不够那种 自动增加 减少
foreach (var num in array)//数组中每个元素找到自己的桶
{
int bit = (int)(10 * num);//标志自己是属于哪个桶
bucket[bit, (int)++bucket[bit, 0]] = num;//先++ 然后利用值 定位到这行 第几个位置
//秒啊(int)++bucket[bit, 0] == bucket[x, 0]表示这一维所包含的数字的个数
}
//为桶里的每一行使用插入排序
for (int i = 0; i < bucketNum; i++)
{
//为桶里的行创建新的数组后使用插入排序
double[] tempArr = new double[(int)bucket[i, 0]];
for (int k = 0; k < tempArr.Length; k++)
{
tempArr[k] = bucket[i, k + 1];
}
//插入排序
StraightInsertionSort(tempArr);
//把排好序的结果回写到桶里
for (int k = 0; k < tempArr.Length; k++)
{
bucket[i, k + 1] = tempArr[k];
//k+1 开始因为0是统计个数的 bucket[x, 0]
}
}
//将所有桶里的数据回写到原数组中
for (int count = 0, j = 0; j < bucketNum; j++)
{// j第几个桶 count 总数从0开始代表目标数组索引
for (int k = 1; k <= bucket[j, 0]; k++)
{
array[count++] = bucket[j, k];
}
}
}
//直线插入排序
public static void StraightInsertionSort(double[] array)
{
//插入排序
for (int i = 1; i < array.Length; i++)
{
double current = array[i];
int j = i - 1;
while (j >= 0 && current < array[j])
{
array[j + 1] = array[j];//往后盖
j--;//继续找
}
array[j + 1] = current;//插入应该在的位置
}
}
}
所以计数排序也利用了 桶排序这种思想 桶一般是5个吧 max-min /5 用list比数组节省空间?? 上面本质上也是空间换时间吧