前言
因为我想到不能光看Unity的教程,也要适当看看算法,进入大厂很看这一方面,而且学习算法的过程还能对自己的编程技能,形成潜移默化的改变,尤其没学过或者对算法不熟悉,遇到可以使用算法解决的问题,自己却不知道自己欠缺哪些部分。所以我打算开启算法的学习。一开始会比较慢,但是学习注重质,而不是量,所以这个不是问题。
在学习的材料中,我选择了慕课网的C++,java算法与数据结构,因为教这门课的老师是一个好老师,对算法的理解肯定比我优秀,代码质量也是。所以我向他学习,并且交上钱,哈哈这样就不好半途而废了,并且看视频的过程比较容易开始,若是直接看算法导论这本书,估计看没几天就看不下去了。
而且事实证明,该视频还是可以的,并且我的学习方法是C++和C#一起学习,这样也让我对C#
的知识点更加多认识,这一次就是来讲讲实现算法帮助的遇到的知识点,虽然暂时只实现在unity的平台上。
知识点
- 泛型编程
- 重写与重载
- 装箱与拆箱
- ref 关键字
- C++的函数指针在C#的替代
- Debug.assert
- IComparable接口的实现
- 选择排序
知识点剖析
1.泛型编程
1.定义,我自己的认识,泛型,也是特殊地类型,不确定指定唯一类型。泛型是为了代码更加灵活,减少代码量。使用了泛型,不同类型都可以使用。
//c++代码
template<Typeof T>
void forCopy(T arr[]){};
//C#代码
void forCopy<T>(T arr[]){};
//特别地,我觉声明时有时候不用加<T> 例如Copy<int>
//但是这种情况就必须了
delegate void Algorithms<T>(T[] arr);
void testAlgorithms<T>(Alforithms<T> func, T[] arr);
上面是我在学习算法过程中使用的代码,接下来将扩展泛型其他的用法。
1。泛型的名字不止可以定义为T,其他也是可以的,尤其是可以描述性的。神奇
public interface ISessionChannel<TSession> { /*...*/ }
public delegate TOutput Converter<TInput, TOutput>(TInput from);
public class List<T> { /*...*/ }
2。类型参数的约束 where T: class ,还可以where f : 基类
对多个进行约束
void findWide<T,F>(int i) where U :struct
where F :struct
3。为泛型集合类或表示集合中的项的泛型类定义接口通常很有用处。 为避免对值类型的装箱和取消装箱操作,泛型类的首选项使用泛型接口,例如 IComparable而不是 IComparable。 .NET Framework 类库定义多个泛型接口,以将其用于 System.Collections.Generic 命名空间中的集合类。
上面官方说的,谨记~~~~
4。C# 泛型的灵活性与 C++ 模板不同。 例如,虽然可以调用 C# 泛型类中的用户定义的运算符,但是无法调用算术运算符。
2.重写与重载
我只说一点,重写是将原有的方法进行改造,而重载是在原有的方法加上对其他类型的操作,二者虽然与需要重“”名的方法一样,但是重写是名和参数类型还有返回类型一样,重载另外一个是参数不一样。
3.装箱与拆箱;
Object obj = 1;//值类型转换到引用类型,
int i = (int)obj//引用类型转换到值类型
之前查到一个网页,讲了在编译器实际发生的过程:分析装箱与拆箱
过程 : 值类型是要放在栈上的,而object是引用类型,它需要放在堆上。这时候需要将栈里的元素取出,然后存到堆中。可以预知这个是耗费CPU的运算时间的。
哈哈,然后还看到使用泛型可以减少装箱拆箱的功能,并且提高了性能
4.ref 关键字
我可以这样理解,就是你对含有ref的关键字进行操作时,会改变原有的值,~让我们来看看。
例如
void Swap<T>(ref T a,ref T b ){
T temp = a;
a = b;
b = temp;
}
...
swap(ref a[0],ref a[1]);//就真的会交换值,哈哈这个估计是C#从C++的指针参考来的,而且还方便一些
...
5.C++的函数指针在C#的替代
使用委托来解决,最简单的委托可以看做是方法的别名(因为方法可以隐式转换给委托),但是也可是很多方法的别名
下面是具体的解决方案,为了传入不同的排序算法
delegeta void SortAlgorithms<T>(T[] arr,int n) : IComparable<T>;
void testSort(String name, SortAlgorithms<T> func,T[] arr,int n) : Tcomparable<T>
{};
6. Debug.assert
我之前一直很困惑,assert在哪里使用,但是现在发现了。比如上面排序算法,排序的大小肯定要正确才行,如果不正确我就不需要计算他所花费的时间。
void testSort(String name, SortAlgorithms<T> func,T[] arr,int n) : Tcomparable<T>
{
Debug.assert(isSorted(arr,n));
};
使用一个断定,代码简洁~
还可以使用在上限必须必下限大的情况。
7.IComparable接口的实现
public class ComparableNum : System.IComparable<ComparableNum>
{
int m_num;
public int num{
get{
return m_num;
}
set {
m_num = value;
}
}
public int CompareTo(ComparableNum other){
return this.num - other.num;
}
}
8. 选择排序的思想
这是个很慢的算法,但是有时候难的算法就是由简单的算法启发得到,并且有些时候,使用简单的算法是更好地选择
void SelectionSort<T>(T arr , int n)
{
for(int i = 0 ; i!=n ; i++){
int minIndex = i;
for(int j = i+1 ; j != n && a[minIndex] > a[j] ; j++)
minIndex = a[j];
swap(a[i],a[minIndex]);
}
}
总结
哈哈,这次呦呦呦写完了。并且我感觉我的代码现在好好看,这篇东西都是我在实现将算法课的C++代码转换到C#遇到的问题,以及解决的方案,看来还是不错的~~~。现在可以去休息拉。