学习过数据结构和算法的,都知道冒泡排序是如何实现的,它是从最前面两个数开始比较,如果前面的数比后面的大,就交换位置,以此类推,使数据完成从小到大的排序。
但是在实际应用中,不可能是只给你一些整型的数据来让你排序,可能是给你一个类,里面有很多属性,我们需要根据其中的一个属性的大小来排序,所以我们需要使用委托,来进行数据的排序。
我们可以举个最简单的的例子,假如在一个公司里有很多员工,我们需要根据他们的工资来进行排序,首先我们要有一个员工类:
class Employee
{
public string Name { get; private set; }
public int Salary { get; private set; }
//构造方法
public Employee(string Name, int Salary)
{
this.Name = Name;
this.Salary = Salary;
}
}
然后我们先写出冒泡排序的方法:
static void Sort(int[] sortArray)
{
//判断数组是否经过排序
bool swapped = true;
do
{
swapped = false;
for (int i = 0; i < sortArray.Length - 1; i++)
{
//判断是否符合前面的数大于后面的数
if (sortArray[i] > sortArray[i + 1])
{
//对两个数进行交换
int temp = sortArray[i];
sortArray[i] = sortArray[i + 1];
sortArray[i + 1] = temp;
swapped = true;
}
}
} while (swapped);
}
现在我们可以开始使用委托和泛型来修改这个方法,使得这个方法适用于其他数据:
static void CommonSort<T>(T[] sortArray,Func<T,T,bool> CompareMethod)
{
bool swapped = true;
do
{
swapped = false;
for (int i = 0; i < sortArray.Length - 1; i++)
{
//因为泛型无法进行比较,所以需要在类里写一个比较大小的方法,并且使用泛型委托
if (CompareMethod(sortArray[i],sortArray[i+1]))
{
T temp = sortArray[i];
sortArray[i] = sortArray[i + 1];
sortArray[i + 1] = temp;
swapped = true;
}
}
} while (swapped);
}
1.首先,因为我们需要进行排序的数据不再是一串整型数据,所以这个排序方法我们需要用泛型来修饰,传入的数组也需要使用泛型。
2. 然后,因为这些是泛型数据,我们不能够再用“>“”<”这两个符号来判断两个数据的大小,所以我们需要在员工类里写一个比较大小的方法,然后使用泛型委托:
//Employee类里的比较方法
public static bool Compare(Employee e1, Employee e2)
{
if (e1.Salary > e2.Salary) return true;
return false;
}
3.在员工类里我们已经将比较薪水大小的方法写好了,然后在排序方法里,我们可以使用Func委托来指向我们这个比较大小的方法,由于还是不知道数据的类型,所以这个委托要写为:Func<T,T,bool> CompareMethod
4.现在原来的冒泡排序也被改写成通用的冒泡排序了,我们在主函数里先创建一个员工数组:
Employee[] employees = new Employee[]
{
new Employee("shdw",23),
new Employee("sdw",452),
new Employee("rthg",234),
new Employee("ngb",123),
new Employee("jyjy",765),
new Employee("awdw",567),
new Employee("cxc",345),
new Employee("erf",789),
new Employee("vde",246)
};
5.然后我们就需要根据员工的薪水来对这个数组进行排序:
CommonSort<Employee>( employees,Employee.Compare );
因为冒泡排序我们是使用泛型来修饰的,所以我们使用这个方法时要指定这个数组的类型。
6.排序之后,我们就要输出这个数组,来验证排序方法是否成功,在这里我们使用foreach方法来对数组进行遍历输出:
foreach (Employee em in employees)
{
Console.WriteLine(em);
}
但是我们会发现输出的结果并不是员工的数据:
因为在这里我们不是遍历变量,而是遍历对象,在遍历对象的时候,编译器会默认调用ToString方法,所以我们需要在员工类里重写ToString方法:
//Employee类
public override string ToString()
{
return Name + ":" + Salary;
}
然后我们再输出一次结果
这样,我们对冒泡排序的改造就完成了,他也可以应用于其他相似的类型。通过这个应用,我们也可以对委托和泛型有进一步的了解。
这里放出源代码:
//员工类
class Employee
{
public string Name { get; private set; }
public int Salary { get; private set; }
public Employee(string Name, int Salary)
{
this.Name = Name;
this.Salary = Salary;
}
public static bool Compare(Employee e1, Employee e2)
{
if (e1.Salary > e2.Salary) return true;
return false;
}
public override string ToString()
{
return Name + ":" + Salary;
}
}
class Program
{
static void CommonSort<T>(T[] sortArray,Func<T,T,bool> CompareMethod)
{
bool swapped = true;
do
{
swapped = false;
for (int i = 0; i < sortArray.Length - 1; i++)
{
//因为泛型无法进行比较,所以需要在类里写一个比较大小的方法,并且使用泛型委托
if (CompareMethod(sortArray[i],sortArray[i+1]))
{
T temp = sortArray[i];
sortArray[i] = sortArray[i + 1];
sortArray[i + 1] = temp;
swapped = true;
}
}
} while (swapped);
}
static void Main(string[] args)
{
Employee[] employees = new Employee[]
{
new Employee("shdw",23),
new Employee("sdw",452),
new Employee("rthg",234),
new Employee("ngb",123),
new Employee("jyjy",765),
new Employee("awdw",567),
new Employee("cxc",345),
new Employee("erf",789),
new Employee("vde",246)
};
CommonSort<Employee>(employees,Employee.Compare);
foreach (Employee em in employees)
{
Console.WriteLine(em); //因为遍历对象的时候,编译器会默认调用ToString方法,所以我们需要重写ToString方法
}
Console.ReadKey();
}
}