【任务目标】
将一组无序数组变为有序
【计数排序原理】
- 找到数组中的最大值Max和最小值Min。那么数组中其他的所有数都在Min和Max之间
- 设置Max-Min+1个桶(盒子、容器,怎么说都可以),每个桶只能装一种数。那么数组中的所有数都能找到对应的桶,桶中数字的个数表示数组中有多少个这样的数。
- 按顺序把桶中的数字取出来,桶内数字个数为0表示改桶内没数字了,继续取下一个桶,直到取完对应数字为Max的桶。此时按顺序取出来的数字是有序的。
【计数排序原理概括】
根据数组中最大值和最小值设置相应数量的有序桶,让数组中的数据在放置过程中自然有序。
【桶排序原理】
在计数排序中,会有很多桶是空的,例如最小值为1,最大值为10000时,会有很多空桶。为了减小桶的数量,让桶内可以放置一定范围内的数字(范围=桶的大小),而不是一种数字。对每个桶内的数字单独排序,随后再将桶内数字按顺序取出,取出来的数字是有序的。
这实际上是将待排序数组划分为了很多小部分(即桶),在小部分中分别排序,这个划分是有选择性的,选择的结果是每个小部分之间是有序的,这和快速排序类似,实际上快速排序中的每个小部分都可以采用其他排序方法,桶排序中每个小部分也可以采用其他排序方法。归并排序虽然也划分了很多小部分,但每个部分之间没有有序性。
【桶排序原理概括】
将无序数组划分为多个有序部分,对每个部分分别排序,连接形成有序数组
【基数排序原理】
对于这样一组数据A={32,87,234,631,126},通过依次比较每个数的个位、十位、百位来比较他们的大小。比较个位时A={631,32,234,126,87}。比较十位时,A={32,126,234,631,87}。比较百位时,A={32,87,126,234,631},此时有序。
设置0~9共十个桶,根据A中数字每位的大小放入对应的桶中,再依次从桶中取出数字。这样有相同位数的数字得到了正确排序,直到所有位置的数字都得到正确的排序,数组就有序了。
【基数排序原理概括】
通过比较数组中不同数字的在不同位数处的大小使得数组有序。
【代码实现】
using System;
using System.Collections.Generic;
using System.Linq;
namespace Sort
{
class Program
{
static void Main(string[] args)
{
int[] A = new int[30];
Random ra = new Random();
for (int i = 0; i < 30; i++)
{
A[i] = ra.Next(200);
}
Program ps = new Program();
ps.BucketSort(A,5);
Console.WriteLine("排序结果:");
foreach (int a in A)
{
Console.Write(a + " ");
}
bool isSorted = true;
for (int i = 0; i < A.Length - 1; i++)
{
if (A[i] > A[i + 1])
isSorted = false;
}
Console.Write(isSorted);
Console.ReadKey();
}
public void CountingSort(int[] A)
{
//找出数组中的最大最小值
int max = 0;
int min = 0;
for (int i = 0; i < A.Length; i++)
{
if (A[i] > max)
{
max = A[i];
}
if (A[i] < min)
{
min = A[i];
}
}
//创建桶,有max-min+1个桶,每个桶只能存放一种数
int[] buckets=new int[max-min+1];
//遍历数组,找出在数组中,在最大值和最小值之间每个数的个数
for (int i = 0; i < A.Length; i++)
{
buckets[A[i] - min]++;
}
//根据桶中每个数的个数排序
int count = 0;//数组下标
for (int i = 0; i < buckets.Length; i++)
{
while (buckets[i]>0)
{
A[count] = i + min;
buckets[i]--;
count++;
}
}
}
public void BucketSort(int[] A,int size)
{
//找出数组中的最大最小值
int max = 0;
int min = 0;
for (int i = 0; i < A.Length; i++)
{
if (A[i] > max)
{
max = A[i];
}
if (A[i] < min)
{
min = A[i];
}
}
//创建桶,每个桶可以存放size种数
int bucketCount = (max - min)/size + 1;
List<List<int>> buckets=new List<List<int>>();
for (int i = 0; i < bucketCount; i++)
{
buckets.Add(new List<int>());
}
for (int i = 0; i < A.Length; i++)
{
int bucketNum = (A[i] - min)/size;
buckets[bucketNum].Add(A[i]);
}
int count = 0;//数组下标
for (int i = 0; i < bucketCount; i++)
{
//对每个桶内的数重新排序,可以用其他排序方法
List<int> bucket= buckets[i];
bucket.Sort();
foreach (int temp in bucket)
{
A[count] = temp;
count++;
}
}
}
public void RadixSort(int[] A )
{
//找出最大值
int max = 0;
for (int i = 0; i < A.Length; i++)
{
if (A[i] > max)
{
max = A[i];
}
}
//求最大值有几位数
int num=0;
while (max>0)
{
max /= 10;
num++;
}
//创建桶
List<List<int>> buckets=new List<List<int>>();
for (int i = 0; i < 10; i++)
{
buckets.Add(new List<int>());
}
for (int i = 0; i < num; i++)
{
//将数组中的元素分配到桶中
for (int j = 0; j < A.Length; j++)
{
//取出345中的十位,先除100取余数,再除10取整数
int remainder = (int) (A[j]%Math.Pow(10, i + 1)/Math.Pow(10, i));
buckets[remainder].Add(A[j]);//添加进对应序号(0~9)的桶中
}
//再将桶中的数据取出放回到数组中
int count = 0;//数组下标
for (int j = 0; j < 10; j++)//桶的标号
{
List<int> curBucket = buckets[j];
while (curBucket.Count>0)
{
A[count] = curBucket[0];//取第一个
curBucket.RemoveAt(0);//移除第一个
count++;//数组下标增加
}
}
}
}
}
}