我从前天开始复习数据结构,这个暑假的主要任务也在此。为了增加反馈,我决定在csdn上写博客。
这是我的第一篇博客,主要是将书上关于抽象数据类型表示和实现的一个例子手打一遍,找点感觉。
/*****抽象数据类型Triplet的表示*****/
typedef ElemType *Triplet;
// ----- 基本操作的函数原型说明 -----
Status InitTriplet(Triplet &T, ElemType v1, ElemType v2, ElemType V3);
// 操作结果:构造了三元组T,元素e1,e2和e3分别被赋予参数v1,v2和v3的值
Status DestroyTriplet(Triplet &T);
// 操作结果:三元组T被销毁
Status Get(Triplet T, int i, ElemType &e);
// 初始条件:三元组T已经存在,1 <= i <= 3
// 操作结果:用e返回T的第i元的值
Status Put(Triplet &T, int i, ElemType e);
// 初始条件:三元组T已经存在,1 <= i <= 3
// 操作结果:改变T的第i元的值为e
Status IsAscending(Triplet T);
// 初始条件:三元组T已经存在
// 操作结果:如果T的三个元素按升序排列,则返回1,否则返回0
Status IsDescending(Triplet T);
// 初始条件:三元组T已经存在
// 操作结果:如果T的三个元素按降序排列,则返回1,否则返回0
Status Max(Triplet T, ElemType &e);
// 初始条件:三元组T已经存在
// 操作结果:用e返回T的三个元素中的最大值
Status Min(Triplet T, ElemType &e);
// 初始条件:三元组T已经存在
// 操作结果:用e返回T的三个元素中的最小值
下面简单分析一下Triplet抽象数据类型的表示。
从typedef ElemType *Triplet;
,可以看到Triplet实际上是指向ElemType的指针。
从函数功能来看,分为以下几类:
- 构造函数:InitTriplet
- 析构函数:DestroyTriplet
- 读取元素的函数:Get
- 设置元素的函数:Put
- 判断元素排列的函数
- 判断是否是升序:IsAscending
- 判断是否是降序:IsDescending
- 获得三元素特征值的函数
- 获得最大值:Max
- 获得最小值:Min
如果从命令查询的责任分离(CQRS)角度来看函数就分为两类:
- Command类型函数,改变三元组的状态
- InitTriplet
- DestroyTriplet
- Put
- Query类型函数,不改变三元组的状态,只读取三元组的信息
- Get
- IsAscending
- IsDescending
- Max
- Min
可以看到,这些函数之间属于通信内聚,它们都是在同一个数据结构,即三元组T上进行操作(Command or Query)。由于这个内聚的特点,所以这些函数的参数中都有Triplet &T(Command类型函数)或是Triplet T(Query类型函数),这在一定程度上造成了代码的冗余。由于教材是以C语言的子集为数据结构的主要描述语言,自然有这种小小的缺陷。在给出这些函数的实现之后,我将以C++面向对象泛型重写Triplet的声明与实现。
下面是与声明对应的实现。
/*****Triplet抽象数据类型的实现*****/
// ----- 基本操作的实现 -----
Status InitTriplet(Triplet &T, ElemType v1, ElemType v2, ElemType V3) {
// 构造三元组T,元素e1,e2和e3分别被赋予参数v1,v2和v3的值
T = (ElemType*) malloc (3 * sizeof(ElemType));
if (!T) {
exit(OVERFLOW);
}
T[0] = v1;
T[1] = v2;
T[2] = v3;
return OK;
} // InitTriplet
Status DestroyTriplet(Triplet &T) {
// 销毁三元组T
if (!T) {
return ERROR;
}
free(T);
T = NULL;
return OK;
} // DestroyTriplet
Status Get(Triplet T, int i, ElemType &e) {
// 1 <= i <= 3,用e返回T的第i元的值
if (i < 1 || i > 3) {
return ERROR;
}
e = T[i - 1];
return OK;
} // Get
Status Put(Triplet &T, int i, ElemType e) {
// 1 <= i <= 3,置T的第i元的值为e
if (i < 1 || i > 3) {
return ERROR;
}
T[i - 1] = e;
return OK;
} // Put
Status IsAscending(Triplet T) {
// 如果T的三个元素按升序排列,则返回1,否则返回0
return (T[0] <= T[1]) && (T[1] <= T[2]);
} // IsAscending
Status IsDescending(Triplet T) {
// 如果T的三个元素按降序排列,则返回1,否则返回0
return (T[0] >= T[1]) && (T[1] >= T[2]);
} // IsDescending
Status Max(Triplet T, ElemType &e) {
// 用e返回T的三个元素中的最大值
e = (T[0] >= T[1]) ? ((T[0] >= T[2]) ? T[0] : T[2])
return OK;
} // Max
Status Min(Triplet T, ElemType &e) {
// 用e返回T的三个元素中的最小值
e = (T[0] <= T[1]) ? ((T[0] <= T[2]) ? T[0] : T[2])
: ((T[1] <= T[2]) ? T[1] : T[2]);
return OK;
} // Min
值得注意的是,以上函数的实现有的并没有对“前置条件”作严格的验证,例如对于初始条件中的“三元组T已经存在”,从Get到Min都没有验证。我想原因在于,InitTriplet先于其他函数执行,已经将条件“三元组T已经存在”进行了验证:如果初始化失败,那么程序终止;如果初始化成功,那么三元组T存在了,可以对它进行其余的操作。
继续看看函数实现中其他值得学习的地方。从IsAscending到Min的实现,没有看到一句if判断,而是有效地利用了逻辑运算和三目运算符。
下面是C++代码的实现。
#include <iostream>
using namespace std;
#include <stdlib.h>
typedef int ElemType;
class Triplet {
private:
ElemType *T;
public:
Triplet(ElemType e1, ElemType e2, ElemType e3) {
T = new ElemType[3];
if (!T) {
exit(1);
}
T[0] = e1;
T[1] = e2;
T[2] = e3;
}
~Triplet() {
delete[] T;
}
ElemType get(size_t index) {
if (index < 0 || index > 2) {
exit(1);
}
return T[index];
}
void set(size_t index, ElemType e) {
if (index < 0 || index > 2) {
exit(1);
}
T[index] = e;
}
bool isAscending(void) {
return (T[0] <= T[1]) && (T[1] <= T[2]);
}
bool isDecending(void) {
return (T[0] >= T[1]) && (T[1] >= T[2]);
}
ElemType max(void) {
return (T[0] >= T[1]) ? ((T[0] >= T[2]) ? T[0] : T[2])
: ((T[1] >= T[2]) ? T[1] : T[2]);
}
ElemType min(void) {
return (T[0] <= T[1]) ? ((T[0] <= T[2]) ? T[0] : T[2])
: ((T[1] <= T[2]) ? T[1] : T[2]);
}
};
int main(void) {
Triplet triplet = Triplet(-1, 0, 1);
cout << "三元组的初始值:" << endl;
for (int i = 0; i < 3; ++i) {
cout << "T[" << i << "] = " << triplet.get(i) << endl;
}
triplet.set(2, 99);
cout << "改变后三元组第3元的值为:" << triplet.get(2) << endl;
if (triplet.isAscending()) {
cout << "三元组升序排列" << endl;
} else {
cout << "三元组降序排列" << endl;
}
cout << "三元组中最大值为:" << triplet.max() << endl;
cout << "三元组中最小值为:" << triplet.min() << endl;
return 0;
}
运行结果: