一、前言
学C#已经两个月了,决定记录和检验一下自己的学习成果。.NET本身不支持Array类型的实例排序,只能用静态方法和Linq实现排序,用扩展方法和泛型给它扩展一下。目标:让代码可以这样写
static void Main(string[] args)
{
char[] array= {'a','e','c','b'};
array.QuickSort();
foreach(char ji in array)
{
Console.WriteLine(ji);
}
array.Reverse();
foreach (char ji in array)
{
Console.WriteLine(ji);
}
}
提示:以下是本篇文章正文内容
二、思路
因为不确定Array是什么类型,所以肯定需要使用T类型。先弄一个比较器Comparer,它继承IComparer接口,在快排算法里依赖注入。
三、实现
1. 构建比较器
每个类型都弄个对应的比较器,这样在快排算法里才会自动找到对应的比较器。最开始我用if(x>y) return 1;if(x<y) return -1;if(x==y) return 0;后来想想直接return x-y就好,最后发现每个方法只有一行,limbda表达式就可以了。
public class IntComparer : IComparer<int>
{
public int Compare(int x, int y)=> x - y;
}
public class UIntComparer : IComparer<uint>
{
public int Compare(uint x, uint y)=> (int)(x - y);
}
public class DoubleComparer : IComparer<double>
{
public int Compare(double x, double y) => (int)(x - y);
}
public class FloatComparer : IComparer<float>
{
public int Compare(float x, float y) => (int)(x - y);
}
public class LongComparer : IComparer<long>
{
public int Compare(long x, long y) => (int)(x - y);
}
public class ULongComparer : IComparer<ulong>
{
public int Compare(ulong x, ulong y)=> (int)(x - y);
}
public class ByteComparer : IComparer<byte>
{
public int Compare(byte x, byte y) => x - y;
}
public class DecimalComparer : IComparer<decimal>
{
public int Compare(decimal x, decimal y) => (int)(x - y);
}
public class SbyteComparer : IComparer<sbyte>
{
public int Compare(sbyte x, sbyte y) => (x - y);
}
public class ShortComparer : IComparer<short>
{
public int Compare(short x, short y) => (x - y);
}
public class UShortComparer : IComparer<ushort>
{
public int Compare(ushort x, ushort y) => (x - y);
}
public class CharComparer:IComparer<char>
{
public int Compare(char x, char y) => (x - y);
}
public class myStringComparer : IComparer<string>
{
public int Compare(string str1, string str2) =>str1.CompareTo(str2);
}
2. 实现快排算法
public static void QuickSorting<T> (T[] array, IComparer<T> comparer,int low, int high)//from small to big
{
if(low>=high)
return;
T index=array[low];
int rightSide=high, leftSide=low;
while(leftSide<rightSide)
{
while(comparer.Compare(array[rightSide],index)>0&&leftSide<rightSide)
{
rightSide--;
}
if(leftSide<rightSide)
array[leftSide++]=array[rightSide];
while(comparer.Compare(array[leftSide],index)<0&&leftSide<rightSide)
{
leftSide++;
}
if(leftSide<rightSide)
array[rightSide--]=array[leftSide];
}
array[leftSide]=index;
QuickSorting<T>(array,comparer,low,leftSide-1);
QuickSorting<T>(array,comparer,rightSide+1,high);
}
3. 调用快排算法
这里费了很多时间,不知道如何获取T的类型,甚至用了反射Activator.CreateInstance(typeof(T)),先建空对象再GetType()。但是测试发现String类型的构造函数必须有参数。最后才用typeof(T).Name解决了这个问题。
public static void QuickSort<T>(this T[] array)
{
switch (typeof(T).Name)
{
case "Int32":
SortingMethods.QuickSorting((int[])Convert.ChangeType(array, typeof(int[])), new IntComparer(), 0, array.Length - 1);
break;
case "UInt32":
SortingMethods.QuickSorting((uint[])Convert.ChangeType(array, typeof(uint[])), new UIntComparer(), 0, array.Length - 1);
break;
case "Double":
SortingMethods.QuickSorting((double[])Convert.ChangeType(array, typeof(double[])), new DoubleComparer(), 0, array.Length - 1);
break;
case "Single":
SortingMethods.QuickSorting((float[])Convert.ChangeType(array, typeof(float[])), new FloatComparer(), 0, array.Length - 1);
break;
case "Int64":
SortingMethods.QuickSorting((long[])Convert.ChangeType(array, typeof(long[])), new LongComparer(), 0, array.Length - 1);
break;
case "ULong":
SortingMethods.QuickSorting((ulong[])Convert.ChangeType(array, typeof(ulong[])), new ULongComparer(), 0, array.Length - 1);
break;
case "Byte":
SortingMethods.QuickSorting((byte[])Convert.ChangeType(array, typeof(byte[])), new ByteComparer(), 0, array.Length - 1);
break;
case "Decimal":
SortingMethods.QuickSorting((decimal[])Convert.ChangeType(array, typeof(decimal[])), new DecimalComparer(), 0, array.Length - 1);
break;
case "SByte":
SortingMethods.QuickSorting((sbyte[])Convert.ChangeType(array, typeof(sbyte[])), new SbyteComparer(), 0, array.Length - 1);
break;
case "Int16":
SortingMethods.QuickSorting((short[])Convert.ChangeType(array, typeof(short[])), new ShortComparer(), 0, array.Length - 1);
break;
case "UInt16":
SortingMethods.QuickSorting((ushort[])Convert.ChangeType(array, typeof(ushort[])), new UShortComparer(), 0, array.Length - 1);
break;
case "String":
SortingMethods.QuickSorting((string[])Convert.ChangeType(array, typeof(string[])), new myStringComparer(), 0, array.Length - 1);
break;
case "Char":
SortingMethods.QuickSorting((char[])Convert.ChangeType(array, typeof(char[])), new CharComparer(), 0, array.Length - 1);
break;
}
}