线性排序-桶排序
桶排序、计数排序和基数排序都是线性排序,原因是这三个算法是非基于比较的排序算法。不涉及元素之间的比较操作。
桶排序
桶排序思想:将要排序的数据分到几个有序的桶里,每个桶里的数据再单独进行排序。桶内排完序后,再把每个桶里的数据按照顺序依次取出,组成的序列就有序了。
数据要求:
- 将排序的数据可以很容易就划分为m个有着天然的大小顺序的桶。
- 数据在桶之间的分布是比较均匀的,如果数据都被划分到一个桶中,时间复杂度为O(nlogn)。
时间复杂度:排序数据共有n个,均匀分布到m个桶内,每个桶内的数据数量为k=n/m,每个桶内部使用快速排序(快速排序时间复杂度为O(nlogn)),即O(mklogk)=O(n*logn/m)。当桶的个数m接近n时,每个桶进行的快速排序时间复杂度为O(1),m个桶时间复杂度为O(m)=>O(n)。
// 桶排序(使用快速排序)
static void Main(string[] args)
{
int[] bucketsort = new int[]{ 22,5,11,41,45,26,29,10,7,8,30,27,42,43,40};
BucketSort(bucketsort,50, 5);//可知每个桶的范围
Console.WriteLine("Hello World!");
}
/// <summary>
/// 桶排序
/// </summary>
/// <param name="a">要排序的数据</param>
/// <param name="max">排序元素最大值</param>
/// <param name="n">桶的个数</param>
public static void BucketSort(int[]a,int max,int n)
{
int[,] bucket = new int[n,a.Length+1];
int size = max / n;
foreach(var item in a)
{
int bucketindex = item / size;
bucket[bucketindex,++bucket[bucketindex,0]] = item;
}
for(int i = 0; i < n; i++)
{
Console.WriteLine($"第{i + 1}桶排序算法结果:");
int[] temarray = new int[(int)bucket[i, 0]+1];
for(int j = 0; j < temarray.Length; j++)
{
temarray[j] = bucket[i,j];
}
QuickSort(temarray, 1, temarray.Length-1);
for(int k = 1; k < temarray.Length; k++)
{
bucket[i,k] = temarray[k];
Console.Write($"{bucket[i,k]} ");
}
Console.WriteLine();
}
}
//快速排序
public static void QuickSort(int[] a,int p,int r)
{
if (p >= r) return;
int q = Partition(a,p,r);
QuickSort(a, p, q - 1);
QuickSort(a, q + 1, r);
}
// 分区函数
public static int Partition(int[] a,int p,int r)
{
var pivot = a[r];
int i = p;
for(int j = p; j <= r - 1; j++)
{
if (a[j] < pivot)
{
int temp = a[i];
a[i] = a[j];
a[j] = temp;
i++;
}
}
a[r] = a[i];
a[i] = pivot;
Console.Write("快速排序:");
foreach(var item in a)
{
Console.Write(item + " ");
}
Console.Write("\n");
return i;
}