作者 内容
 wangkangyuan  赐教:关于类派生和模式
 

我现在想写一个关于矩阵的数据结构类集,应该说比较经典。我刚开始的思路是这样的。矩阵类是基类,下面派生两个类:方阵和稀疏矩阵。在方阵后再派生两个类:三角阵和对称阵。在稀疏矩阵中派生两个类:一个实现三元组,一个实现十字链表。
但是很快我发现这个想法是错误的,因为稀疏矩阵只是矩阵的一种实现方法,而方阵才是真正的特殊矩阵。同样三角阵是矩阵的一种存储方法,是解决对称阵的一种存储方法。
想到这么一个问题,我又想通过bridge模式来解决这个问题,即总基类为矩阵和矩阵实现,在矩阵中派生方阵和对称阵。在矩阵实现中派生三角阵和稀疏矩阵。在稀疏矩阵下再派生三元组和十字链表。
当时为自己的想法还很高兴,但过一会儿就发现一个问题。数据结构本身是存储数据的。如果将数据存储方法和操作分开。那好像就没办法来写程序了。不知哪位大侠能够告诉我究竟该怎么来分析这类数据结构问题。
万分感谢

 02/06/27 20:42 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 w_rose   回复: 赐教:关于类派生和模式
 

所有的矩阵都是一种普通矩阵(m行n列)。他们有同样的计算方法(乘、加、逆、特征值等等)。因此你先实现普通矩阵,并且开发用到矩阵运算的客户程序,以后再逐步开发各种特殊矩阵,继承普通矩阵。

但是内部实现是不一样的。因此你可以针对某种特殊矩阵实现自己的计算方法,这个方法覆盖(或者叫做对消)了它的父类的同样方法,以便提高计算效率。如果某个计算方法与父类相同,就不必覆盖,程序会自动从父类继承计算方法。

你的别处的程序可以使用矩阵类。比如计算:A的逆左乘B。你可以将A和B声明为普通矩阵,首先保证程序计算正确。以后,如果你知道A其实是三角阵,并且三角阵计算逆比普通矩阵快一个数量级(我只是打个比方),你可以将表达式前A的类型变为三角阵,仅仅用几秒钟的时间,整个程序的实际交给CPU的运算代码彻底改变了!

什么叫做隐藏实现方法呢?比如取出矩阵A的x行y列的值,普通阵的操作是到二维数组的[x,y]位置取得值,而三角阵只需要一半的存储空间(使用一维数组),但是任何客户程序不用管它是怎么存储的,反正调用A的操作value(x,y)就行了。不论你将三角阵随时改为任何其它结构,那些程序都不需要重新改写和编译,并且运行结果保证是一样的。可能你的程序有100行运算要耗时10个小时,但是将程序开头变量定义部分定义A改一下,后面的运算表达式不用改,程序会自己知道何时使用三角阵的自己的计算法的。

 02/06/27 21:34 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 w_rose   回复: 赐教:关于类派生和模式
 

如果你希望多分几层(虽然我感觉没很大必要),那么稀疏阵显然在方阵和非方阵中都有,则简单方法还是从普通矩阵中继承。如果你偏要有个稀疏方阵,则既可以从方阵中继承,也可以从稀疏阵中继承,或者两个分别都提供。

不要说“稀疏阵只是矩阵的一种实现方法”这种话。你所说的任何名词都可以实现为一个单独的类,只是看你愿不愿意。稀疏阵是类,稀疏阵的方法才是一种实现方法——有点废话吧!

在我们的自然语言中,稀疏阵可能指一种类、一个这个类的实例,也可能值代她自己的实现过程呢!我们的自然语言就是容易含混呀。

 02/06/27 21:50 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 w_rose   我有个失误,只有方针才有逆和特征值。你的方阵继承普通矩阵同时增加新的操作就行了。
 
 02/06/27 21:57 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 wangkangyuan  回复: 赐教:关于类派生和模式
 

谢谢,但我还是有一点不明,如果稀疏阵是从普通矩阵中继承,方阵从稀疏阵中继承,那么方阵也用的是稀疏阵的方法,他怎么用别的方法呢?如果方阵直接从普通阵继承,那么他用不了稀疏阵的方法?而且稀疏阵我在实现时希望用三元组或十字链表两种方法来实现,我希望在类中两种都能够实现,到时候根据情况选一种就可以了。这个应该怎么实现?

 02/06/27 21:58 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 w_rose   回复: 赐教:关于类派生和模式
 

方针不能从稀疏阵中继承,因为有些方针不适稀疏的。稀疏方针你可以从方阵中继承。由于现在有效(执行比较快)的编程语言大多不支持多重继承,所以你无法同时继承方针和稀疏阵。你可以在稀疏方阵中定义一个内部变量A,类型为稀疏阵,稀疏方针自己不保存任何数据,将数据保存到A中,这样你具有了方针的全部操作和稀疏阵的存储优势。

如果你有多种实现稀疏阵的方法都要实现,你就得细分为设计“十字链表稀疏阵”、“三元组稀疏阵”(你可以将任何一个作为“稀疏阵”的标准方法,其他的从她继承并在内部改变,也可以实现纯虚拟的稀疏阵类)。外部任何操作,只要是能针对基本稀疏阵操作的,以后都不需要重新改变和测试。

 02/06/27 22:11 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 wangkangyuan  不知我这样理解对不对
 

class CMatrix{
public:
operator +;
operator -;
operator *;
public:
CMatrixStore* matrixStore;//存储类的变量
};

CMatrix::CMatrix{
matrixStore = new(CSparseStore)//或十字链表、三元组
};

class CMatrixStore
{
public :
Get(int i,int j,template &value);//实现设置值和得到值
Set(int i,int j,template value);
};

class CSquareMatrix:public CMatrix //方阵从矩阵继承
{
public:
reverse();//求逆
};

class CSpareseMatrixStore : public CMatrixStore
{
};

class CSparseMatrixStoreWithThreeElement : public CSpareseMatrix
{
typedef struct
{
int i,j;
template value;
}ThreeElement;
typedef struct
{
int mu,nu,tu;
ThreeElement* element;
}ThreeElementArray;
//重载get和set
};

class CSparseMatrixStoreWithCrossLink : public CSparseMatrix
{
//十字链表数据结构
//重载get和set
};

不知这样正不正确

 02/06/27 22:45 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 w_rose   回复: 不知我这样理解对不对
 

class CMatrix{
public:
operator +;
operator -;
operator *;
public:
CMatrixStore* matrixStore;//存储类的变量

};
不应当定义为public,应当直接提供Get和Set访问单元数值。使用OO风格纯粹是为了实用的目的,因此往往只是“对自己要求是否严格”的问题。严格使用“纯”OO的好处是烦锁和重复的地方很少,因此失误相对很少,调试相对很容易。

 02/06/29 12:16 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首
 wangkangyuan  回复: 不知我这样理解对不对
 

谢谢,我在程序中已经改了

 02/06/29 19:54 酷帖!    臭帖!    回复  
酷帖评价:           臭帖评价:
返回页首