抽象数据类型Triplet的表示和实现

我从前天开始复习数据结构,这个暑假的主要任务也在此。为了增加反馈,我决定在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;
}

运行结果:
这里写图片描述

  • 12
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值