您的位置:首页 > 编程语言 > Go语言

Dragon第二阶段-图算法-开发总结

2010-02-28 20:34 211 查看
从2月2日--2月28日,刚好一个月的时间才完成全部图算法,编码速度有待提高。下面内容是本开发阶段的总结。



主要有以下几个部分:

1. 开发过程完成的模块,算法以及技术点

2. 开发过程中遇到的问题以及解决方法

3. 开发过程中遗留的问题

4. 下一阶段开发的计划

1. 开发过程中完成的模块,算法以及技术点

(1)堆数据结构,优先队列数据结构。 (2.2--2.4)

(2)图数据结构 (2.5-2.6)

(3)队列数据结构 (2.6)

(4)深搜,(2.8)

广搜,(2.7)

拓扑排序,(2.8)

强连通分支 (2.9--2.11)

(5)最短路:Bellman-Ford,(2.11)

Dijkstra,(2.17--2.22 后面发现还有问题)

矩阵乘法算法(未优化)(2.23--2.24)

Floyd-Warshall (2.24--2.25)

Johnson(2.25--2.28)

技术点包括:友元,模板友元,向模板类传入模板类作为类型参数,遗漏的在错误汇总中补上。

2. 开发过程中最重要的反思:

(1)单元测试一定要非常严格,不然在这种模块协作的程序中 垒得越高,出现的错误就越难查,看来程序正确性验证这门学问真的非常有用!

(2)接口一定要清晰定义。曾经不止一次遇到由于输入数据不正确或程序作出修改后导致输入数据不匹配导致的错误。

函数接口的错误还比较容易差,但是像这样的输入输出接口导致的错误就很难查到了。



典型错误列表:

(1)类方法中不能这样写: virtual LinearList<T>* ToLinearList() =0 const ; 要把=0删去

(2)在C++中,注意不能这样定义一些类中的对象:Heap<T> m_pHeap; 特别是Heap是一个虚类时会报错。因为这样写不是表示声明,而是直接调用构造函数定义了。所以要使用对象的时候用指针吧。

(3)const T 不能转换为T, T转换为const T可以。

(4)枚举不能跟整型自由地(隐式地转换)只能由
整型常量表达式来初始化。 的解决方案是使用一个namespace,将枚举和静态常量封装进去,在一个模板类里面定义枚举,在外部无法使用(指的是无法使用枚举中的常量)

(5)编译的时候一定是先声明类型,然后定义变量,一定是按顺序进行的,比较不够智能化。

(6)定义虚函数如果不写virtual func() = 0, 就会出:外部链接错误,无法找到nresolved external
symbol "public: virtual void __thiscall
Heap<int>::Modify(int,int)"
(?Modify@?$Heap@H@@UAEXHH@Z),那么应该说前天的虚析构函数也能解决了。这个错误发生了两次。

(7)运行中出现的问题:向优先队列入队时没有使堆结构发生变化。原来堆的设计中还存在问题,那就是没有考虑向上作堆性质维护的情况。

比如:在最大堆里面,修改其中一个结点的关键字,使之变大,之后激发的操作应该是向上维护堆性质。而目前的MaintainHeap都是向下维护,而算法书上的优先队列提供的算法的情况是:最小优先队列--IncreaseKey---只能increase!!!



-------------------------------------------------------------------------------------------------------------------------

(8)模板类的友元函数声明:C++PL里面的说法是:friend Vector func<>(...) 改后的确识别出是友元,但是仍然有许多错。

实践中能够正确运行的友元函数声明:template <typename E>friend void PrintGraph(GraphAdjMatrix<E> &graph);



(9)模板类的声明:template<class T>class Matrix! 注意!!而且要注意的是,如果声明放在命名空间中,则不管这个类在哪里实现,引用的时候都需要指定命名空间。后面有一个错与其相关。



-------------------------------------------------------------------------------------------------------------------------

(10)Insert方法出现问题,当插入需要扩张后,未能获得原来的句柄。

解决:其实原来的方法是错误的!!! 不需要构造一个LinerList。。。只需要构造一个T* 划出一个新的连续内存区域即可!!!



(11)Dijkstra算法中如何实现的问题。按书上算法无法实现,因为涉及在队列中删除元素的操作。而在优先队列中定位元素并不是O(1)复杂度的操作。而真正的实现方法(能够利用好优先队列的特性)的方法应该是往队列中添加节点。



(12)模板类的类型参数 不可以是模板, 只有模板函数的类型参数可以是模板,这一点要记住。

而要实现往一个优先队列里添加 模板类类型 的元素, 目前试验可行的一个方法是:

typedef QueueItem<E> _QueueItem

使用typedef 这样就可以瞒过编译器了?

(13)这个错误很值得注意,在Java中,可以在一个构造函数中调用另一个构造函数来实现构造过程,而在C++中,这样做导致的结果是构造出来的对象句柄没有被返回,即 作为构造目标的对象 只根据调用的构造函数来产生,而这个函数是通过调用另一个构造函数来实现,即本身并没有实现任何数据初始化,使得出错。

(14)还有一些其他的错误,主要属于算法上,语法上,细心上等等。这里就不一一列举了。



3. 开发过程中遗留的问题

(1) 图:GraphAdjMatrix中缺乏Graph接口中定义的AddVex,DeleteVex,AddEdge,DeleteEdge等接口的实现。

(2)堆:二项堆,斐波拉切堆的实现

(3)各种日志操作,各种Assertion,健壮性缺陷很大

(4)图的遍历算法(深搜 广搜)中的泛型算子的实现不是很好

(5)DAG图的最短路径没实现

(6)Matrix Multiplication的优化没实现。而且那一段代码可以重构

(7)传递闭包没实现。



4. 下一阶段的开发计划

(1)完成DLL的生成

(2)树相关数据结构的实现:红黑树,平衡二叉树,B树 B+树

(3)不相交集合的实现

(4)最小生成树算法

(5)哈希表实现

(6)Map, 字典数据结构的实现
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: