最近笔者通过哈工大的软件构造课程,学习了抽象数据类型.
我们,将通过打比方的形式,通俗易懂的给大家讲明白ADT是谁,为什么要有这个东西,以及,怎么构建它

ADT:抽象数据类型

定义:抽象数据类型(Abstract Data Type,ADT)是计算机科学中具有类似行为的特定类别的数据结构的数学模型;或者具有类似语义的一种或多种程序设计语言的数据类型。抽象数据类型是间接定义的,通过其上的可执行的操作以及这些操作的效果的数学约束(与可能的代价)。
按照MIT的说法,ADT可以用下面的这幅图来进行描述:


直观的看,ADT就是一道墙,将内在的表示与外部的使用进行隔离这种隔离,通过接口进行的间接访问,降低了代码块与块之间的耦合性.

下面的两个比喻,形象生动的说明了ADT是干什么的,为什么这么重要:

  1. 就像盖房子,我们写的软件代码,java里面一个个的Class,就像很多的***普通的砖头***,我们并不需要他们每一个都那么的独领风骚,我们需要每一块砖头都长得差不多,标准一致,这样可以进行将砖头进行千百次的堆砌.同时,我们需要一块砖头如果觉得它存在质量问题,我们可以马上用另一块相似的砖头进行代替.

  2. 就像军舰里面的***水密隔舱***,通过一层一层的将船与外面的大海进行隔离,那么如果一侧因为中弹而进水,将防水门一关,进水将不会影响到军舰的其余部分.

为了能够造出更规则统一的砖头(水隔舱),无数计算机领域的巨佬,研究出ADT这样的指导思想,帮助外面更好的,造出统一而又安全的砖头.

可变与不可变数据类型

还是使用砖头来作比方:
如果我们想要自己用砖头搭建起来的房子是可以平稳存在的,那么,我们就首先得要求这个砖头,它是稳定的.
不可变数据类型就像是一块死砖头,它不会因为外界的操作而改变自己的属性,可以说这个砖头,它是死的.我们就可以依靠这个砖头来作房子的地基.从而使房子四平八稳.

比如说,上图的字符串String,就是不可变的,它如果对其进行操作,会直接返回新的一个对象
那么,如果我们的代码里面用了可变的数据类型,它会带来什么后果呢?

直接给外界你内部的属性的指针,让外界直接对内部属性进行修改.导致一些很阴间的bug.
比如:神不知鬼不觉的,数据结构内部属性的值一下子就变了…

/*** @return the first day of spring this year*/
public static Date startOfSpring() {return askGroundhog();
}
********************************************
// somewhere else in the code...
public static void partyPlanning() {Date partyDate = startOfSpring();// ...
}
/*** @return the first day of spring this year*/
public static Date startOfSpring() {if (groundhogAnswer == null) {groundhogAnswer = askGroundhog();}return groundhogAnswer;
}
private static Date groundhogAnswer = null;
**********************************************
// somewhere else in the code...
public static void partyPlanning() {// let's have a party one month after spring starts!Date partyDate = startOfSpring();partyDate.setMonth(partyDate.getMonth() + 1);// ... uh-oh. what just happened?
}

所以,正如大厦的地基必须要用混凝土和坚实的砖石来打,程序内部所依靠的数据类型,最好是采用不可变的数据类型

Spec 规约

假如我们是来给别人家房子的施工队,在出发之前,一般都是要和雇主甲方爸爸签一个文书的,这个就是规约Spec

这个spec,它通过规定双方的责任,也就是产品问题,找谁说理去.
细分为两大类:
前置条件: 如果产品坏了,这个责任在用户.
后置条件: 如果产品坏了,这个责任在施工队.

在我们写Java程序时,其实,也有这样的一个spec要去完成
它长这样:

/*** Find a value in an array.* @param arr array to search, requires that val occurs exactly once*            in arr* @param val value to search for* @return index i such that arr[i] = val*/
static int find(int[] arr, int val)

不难发现里面的前置与后置可以大致分下:

前置条件
@param arr array to search, requires that val occurs exactly once in arr
@param val value to search for
find(int[] arr, int val)
后置
Find a value in an array.
@return index i such that arr[i] = val

它就像一个防火墙,隔绝开了用户与程序内部的表示.

换一种视角 数据->操作

如果我们对之前学的数据结构与算法换一种视角来看,我们的数据结构其实可以被一组操作进行刻画.

比如说,以我手里的茶杯为例

它作为一名普普通通的茶杯,它可以用以下操作来刻画

class TeaCup{/*** 喝茶*/public Drink(){};/*** 倒茶*/public Fill(Water Tea){};
}

我们作为21世纪的消费者,是不需要了解这个茶杯它是用硅酸盐组成的.然后里面添加了什么样子的化学物质来进行塑性等待的细节.我们使用的,只是它给我们的两个方法:喝茶,倒茶.

ADT也一样,我们给外界的 是一组操作,而非内部的表示.

四大er,四种方法

具体来说,这些操作可以细分为四大方法:
以杯具的一生为例:

构造器 : 凭空直接给你造出一个茶杯
生产器 : 放入一个白色的茶杯,与一些颜料,给你返回一个黑色的茶杯
观察器 : 看下茶杯是否为空的,里面的茶叶是什么品种的.
变值器 : 放入一个空茶杯,返回一个打满了茶水的茶杯.

来一点数学: 抽象函数AbstractFunction

我们上面说了这么多,其实可以用一个简单的数学映射加以描述

AF(内在表示) ==> 抽象值

程序员需要利用号内在的表示值,同时编写程序,来进行映射,向外界提供观测,修改抽象值的接口.

这便是抽象.
通过抽象,隐藏底层复杂的实现细节,将间接,可靠一致的抽象操作提供给外界,从而达到降低系统整体的耦合度的效果.

底层的实现细节就是R空间.而用户关注的空间,或者说,我们给用户呈现的空间,就是A空间,即抽象空间.

下面就是一个例子,通过抽象函数,我们将字符串映射到了集合空间A里面.


左边的R,是Representation,即数据表示.这个,便如我们施工队的比方,是我们房子下面的地基.
这个地基,必须要稳,否则房子本身就是不稳定的,有害于人民群众的财产安全.

所以,我们作为ADT的编写者,有责任去做点事情,来确保这个房子是稳定的.
体现为:

RI 表示不变量

还是以集合为例,我们用按顺序排列的字母来队这个集合进行表示,所有串里面的字符排列,必须是升序的.
这个升序,就是RI,它对表示空间进行了划分,将我们用到的合法的值,映射为true,其余为false
用函数的角度来说

RI(表示)==>{true,false}


我们还可以在代码里面对这个进行检查,因为只要我们的表示什么时候被RI给映射到了false,那么就意味着,我们的代码出bug了…

上述内容便是ADT的一些介绍,谢谢大家.

一篇通俗易懂的ADT介绍相关推荐

  1. CCNA-第十五篇-DHCP配置+SDN介绍(最后一章)

    CCNA-第十五篇-DHCP配置+SDN介绍 各位好,如果有一直看下来的谢谢支持 这里是CCNA的最后一篇了,如果真的能吸收很多内容,那么普通的东西基本上都没什么大问题了.除非就是工作经验 下一篇就到 ...

  2. Swift 面向协议编程 基础篇 (一) 介绍

    前言 好久没有写文章了,期末复习周也到了.在复习的同时顺便开了一个专题,面向协议编程,[ 基础篇 ],[ 进阶篇 ],[ 实践篇 ]. 介绍 首先,面向对象(OOP)大家并不陌生,苹果的很多框架都是以 ...

  3. 这是小小本周的第六篇,本篇小小将会介绍一个很古老很古老很古老的为什么系列之不能重写service方法。...

    这是小小本周的第六篇,本篇小小将会介绍一个很古老很古老很古老的为什么系列之不能重写service方法. 小小最近看到一年一度的考研,心生感慨,不过,作为一个专科,没法参与今年的考研,但是没关系,小小明 ...

  4. iOS开发UI篇—常见的项目文件介绍

    iOS开发UI篇-常见的项目文件介绍 一.项目文件结构示意图 二.文件介绍 1.products文件夹:主要用于mac电脑开发的可执行文件,ios开发用不到这个文件 2.frameworks文件夹主要 ...

  5. iOS开发UI篇—UIScrollView控件介绍

    iOS开发UI篇-UIScrollView控件介绍 一.知识点简单介绍 1.UIScrollView控件是什么? (1)移动设备的屏幕⼤大⼩小是极其有限的,因此直接展⽰示在⽤用户眼前的内容也相当有限 ...

  6. SAP那些事-理论篇-12-SAP五层体系介绍

    如果您觉得这篇文章对你所有帮助的话,您的顺手点赞和转发将是对作者持续发文的重要动力,您的支持和鼓励很重要! 所有文章在公众号"MZ信息化咨询杂谈"同步更新! 郑重声明:本博客所发文 ...

  7. 5G网络实现自动驾驶车联网——第一篇:5G模块介绍实现上网功能

    5G网络实现自动驾驶车联网--第一篇:5G模块介绍实现上网功能 大家好我是Jones,写博客记录一下工作的痕迹,同时也对工作做一个总结,才疏学浅,难免会有很多纰漏,还请大家批评指正,创业初期,欢迎技术 ...

  8. Windows内网协议学习NTLM篇之NTLM基础介绍

    0x00 前言 这个系列文章主要讲ntlm认证相关的内容.以及着重介绍ntlm两大安全问题–PTH和ntlm_relay. ntlm篇分为四篇文章 第1篇文章也是本文,这篇文章主要简单介绍一些基础概念 ...

  9. 国企央企OFFER收割全攻略 | 银行篇之行业整体介绍

    国企央企OFFER收割全攻略 | 银行篇之行业整体介绍 大家好,这里是小黛.最近完成了一些工作上的事情,因此更新推迟了一些. 这篇银行求职全攻略,千呼万唤始出来,耗费了小黛非常非常非常多的心血,反复加 ...

最新文章

  1. 子域名绑定html,DEDE二级域名(多站点)绑定详解
  2. 区块链相关论文研读5:分布式隐私保护可审计的账本,zkLedger
  3. python 获取文件大小,创建时间和访问时间
  4. 安装python环境与运行_专栏G|轻松学Python01:Python环境搭建与运行
  5. python xlwt单元格合并_Python xlwt写入单元格并合并单元格操作问题,pythonxlwt,我想展示成这样:----...
  6. LeetCode 226. 翻转二叉树(DFS BFS)
  7. 测试专员如何编写优秀的测试代码·单元测试篇
  8. ❤️大佬都在学什么?Python爬虫分析C站大佬收藏夹,跟着大佬一起学, 你就是下一个大佬❤️!
  9. Flutter学习资源汇总(不定期更新)
  10. 完美二叉树, 完全二叉树和完满二叉树
  11. DSO(Direct Sparse Odometry)
  12. 360服务器被劫持怎么修复,360浏览器网络劫持导致主页被改怎么办?360浏览器网络劫持导致主页被改的解决办法...
  13. 尝试用朴素贝叶斯分析借款信用等级
  14. 从卷积到residual dense network: Convolution, ResNet, DenseNet and ResDenseNet解读
  15. [原创]通过动态Sql语句,一次性彻底删除或者修改SBO的某个字段对应内容的信息...
  16. 对象存储入门 [ minIo ozone ]
  17. 坚果Pro和罗永浩的锤子梦
  18. Git断开与原来远程仓库连接,连接新仓库并重新上传
  19. 浙江大学计算机博士2019,浙江大学召开2019年博士生招生录取工作会议
  20. “希希敬敬对”Alpha版本发布说明

热门文章

  1. ManagementClass——ManagementClass 构造函数 (ManagementPath)
  2. java程序员提升必备大数据、架构师学习资料免费分享
  3. lxc mysql 使用_LXC容器
  4. 关于工业以太网交换机,你应该知道这些
  5. RTP与RTCP协议简述
  6. 思科路由器-配置RIPv2
  7. 基于知识图谱的《红楼梦》人物关系可视化及问答系统的实现
  8. 【每日英文】2021.10.12
  9. Linux系统搭建钓鱼WIFI教程,Kali linux创建钓鱼wifi热点
  10. quartz (从原理到应用)详解篇