1.怎样写一个抽象数据类型
template
这样在编写程序过程就比较麻烦。比如要写一个两个数相加的函数 int add(int a,int b),可以看到,这个函数只支持int 类型,float,double等类型就不能用这个函数了,只能再写一个 float addf(float a,float b)。
这样代码的重用性能不好。到了C++就有模版的出现了就是定义一个模版,传入参数类型是不定时,就可以定义为模版。
你的代码就是了,template
当编译成目标文件后,模版在定义变量赋了什么类型就是什么类型了。
2.抽象数据类型有什么用
首相数据类型,泛指除基本数据类型以外的数据类型。什么叫类型?就是一类数据。基本数据类型被人做是最基本地,不可再划分的数据,一般就是整形、浮点型、以及字符型。抽象数据类型是由若干基本数据类型归并之后形成的一种新的数据类型,这种类型由用户定义,功能操作比基本数据类型更多,一般包括结构体和类。其实说白了,抽象数据类型就是把一些有一定关联的基本数据类型打包,然后当做新的数据类型使用。
至于有什么用,这个用处可大了。比如你要实现对一个人地信息管理,如果你只用基本数据类型那么你需要定义很多数据类型的变量比如名字、性别、出生地、生日之类的,并且操作起来不方便。如果用抽象数据来实现就简单了,直接把这些信息放包装在一个新的数据类型中,然后就可以直接定义这样的一个变量就可以了。
C++中的类更好的实现了封装功能,这就是类。类使得抽象数据类型的可操作性更强了,真正实现了面向对象。至于用法,只要学过C++肯定知道类地用法吧?那就是如何用。也许你现在觉得这样的操作更麻烦了,还不如C语言简洁的好。但是当你有一天真正的进入了公司,你才发现面向对象编程是多么棒的一种编程方式,他可以让你更高效的去开发。
同时告诉你,你对负责操作不是很了解只能证明你的编程数量不够,在编程领域中永远要记住一句话:钢是打出来的。编程仅仅靠看书或是听老师讲解是行不通的,必须亲自躬行才能真正掌握它
3.怎样写一个抽象数据类型
template 这是定义类模版
因为C语言的函数参数传递需要指定确定类型才行。这样在编写程序过程就比较麻烦。比如
要写一个两个数相加的函数 int add(int a,int b),可以看到,这个函数只支持int 类型,float,double等类型就不能用这个函数了,只能再写一个 float addf(float a,float b)。这样代码的重用性能不好。
到了C++就有模版的出现了
就是定义一个模版,传入参数类型是不定时,就可以定义为模版。
你的代码就是了,template class T是任意的类型。
这样需要说明的是,模版的类型转换过程是发生在编译之前,也就是预编译,预编译跟预处理不同,预处理纯粹是编译前宏代码的替换,预编译是开始编译后,对一些模版类型进行调整生成中间代码,当然还有其它一些工作。
当编译成目标文件后,模版在定义变量赋了什么类型就是什么类型了
4.抽象数据类型
类的基础:抽象数据类型抽象数据类型(ADT, abstract data type)是指一些数据以及对这些数据所进行的操作的集合。
这些操作既向程序的其余部分描述了这些数据是怎么样的,也允许程序的其余部分改变这些数据。“抽象数据类型”概念中“数据”一词的用法有些随意。
一个ADT可能是一个图形窗体以及所有能影响该窗体的操作;也可以是一个文件以及对这个文件进行的操作;或者是一张保险费率表以及相关操作等等。要想理解面向对象编程,首先要理解ADT。
不懂ADT的程序员开发出来的类只是名义上的“类”而已——实际上这种“类”只不过就是把一些稍有点儿关系的数据和子程序堆在一起。然而在理解ADT之后,程序员就能写出在一开始很容易实现、日后也易于修改的类来。
传统的编程教科书在讲到抽象数据类型时,总会用一些数学中的事情打岔。这些书往往会像这么写:“你可以把抽象数据类型想成一个定义有一组操作的数学模型。”
这种书会给人一种感觉,好像你从不会真正用到抽象数据类型似的——除非拿它来催眠。把抽象数据类型解释得这么空洞是完全丢了重点。
抽象数据类型可以让你像在现实世界中一样操作实体,而不必在低层的实现上摆弄实体,这多令人兴奋啊。你不用再向链表中插入一个节点了,而是可以在电子表格中添加一个数据单元格,或向一组窗体类型中添加一个新类型,或给火车模型加挂一节车厢。
深入挖掘能在问题领域工作(而非在底层实现领域工作)的能量吧!Example of the Need for an ADT需要用到ADT的例子为了展开讨论,这里先举一个例子,看看ADT在什么情况下会非常有用。有了例子之后我们将继续深入细节探讨。
假设你正在写一个程序,它能用不同的字体、字号和文字属性(如粗体、斜体等)来控制显示在屏幕上的文本。程序的一部分功能是控制文本的字体。
如果你用一个ADT,你就能有捆绑在相关数据上的一组操作字体的子程序——有关的数据包括字体名称、字号和文字属性等。这些子程序和数据集合为一体,就是一个ADT。
如果不使用ADT,你就只能用一种拼凑的方法来操纵字体了。举例来说,如果你要把字体大小改为12磅(point),即高度碰巧为16个像素(pixel),你就要写类似这样的代码:currentFont.size = 16如果你已经开发了一套子程序库,那么代码可能会稍微好看一些:currentFont.size = PointsToPixels(12)或者你还可以给该属性起一个更特定的名字,比如说:currentFont.sizeOnPixels = PointsToPixels(12)但你是不能同时使用currentFont.sizeInPixels和currentFont.sizeInPoints,因为如果同时使用这两项数据成员,currentFont就无从判断到底该用哪一个了。
而且,如果你在程序的很多地方都需要修改字体的大小,那么这类语句就会散布在整个程序之中。如果你需要把字体设为粗体,你或许会写出下面的语句,这里用到了一个逻辑or运算符和一个16进制常量0x02:currentFont.attribute = CurrentFont.attribute or 0x02如果你够幸运的话,也可能代码会比这样还要干净些。
但使用拼凑方法的话,你能得到的最好结果也就是写成这样:currentFont.attribute = CurrentFont.attribute or BOLD或者是这样:currentFont.bold = True就修改字体大小而言,这些做法都存在一个限制,即要求调用方代码直接控制数据成员,这无疑限制了currentFont的使用。如果你这么编写程序的话,程序中的很多地方就会到处充斥着类似的代码。
Benefits of Using ADTs使用ADT的益处问题并不在于拼凑法是种不好的编程习惯。而是说你可以采用一种更好的编程方法来替代这种方法,从而获得下面这些好处:可以隐藏实现细节 把关于字体数据类型的信息隐藏起来,意味着如果数据类型发生改变,你只需在一处修改而不会影响到整个程序。
例如,除非你把实现细节隐藏在一个ADT中,否则当你需要把字体类型从粗体的第一种表示变成第二种表示时,就不可避免地要更改程序中所有设置粗体字体的语句,而不能仅在一处进行修改。把信息隐藏起来能保护程序的其余部分不受影响。
即使你想把在内存里存储的数据改为在外存里存储,或者你想把所有操作字体的子程序用另一种语言重写,也都不会影响程序的其余部分。 改动不会影响到整个程序 如果想让字体更丰富,而且能支持更多操作(例如变成小型大写字母、变成上标、添加删除线等)时,你只需在程序的一处进行修改即可。
这一改动也不会影响到程序的其余部分。让接口能提供更多信息 像currentFont.size = 16这样的语句是不够明确的,因为此处16的单位既可能是像素也可能是磅。
语句所处的上下文环境并不能告诉你到底是哪一种单位。把所有相似的操作都集中到一个ADT里,就可以让你基于磅数或像素数来定义整个接口,或者把二者明确地区分开,从而有助于避免混淆。
更容易提高性能 如果你想提高操作字体时的性能,就可以重新编写出一些更好的子程序,而不用来回修改整个程序。让程序的正确性更显而易见 验证像currentFont.attribute = current-Font.attribute or 0x02这样的语句是否正确是很枯燥的,你可以替换成像currentFont.SetBoldOn()这样的语句,验证它是否正确就。
5.线性表的抽象数据类型怎样描述
线形表的抽象数据定义
ADT List{
数据对象:D={ai|ai∈ElemSet,i=1,2,……,n,n≥0}
数据关系:R1={<ai-1,ai>|ai-1,ai∈D,i=2,……,n}
基本操作:
InitList(&L)
操作结果:构造一个空的线性表L。
DestroyList(&L)
初始条件:线性表L已存在。
操作结果:销毁线性表L。
ClearList(&L)
初始条件:线性表L已存在。
操作结果:将L重置为空表。
ListEmpty(L)
初始条件:线性表L已存在。
操作结果:若L为空表,则返回TRUE,否则返回FALSE。
ListLength(L)
初始条件:线性表L已存在。
操作结果:返回L中数据元素个数。
GetElem(L,i,&e)
初始条件:线性表L已存在,1≤i≤ListLength(L)。
操作结果:用e返回L中第i数据个元素的值。
LocateElem(L,e,compare())
初始条件:线性表L已存在,compare( )是数据元素判定函数。
操作结果:返回L中第1个与e满足关系compare(
)的数据元素的位序。若这样的数据元素不存在,则返回值为0。
PriorElem(L,cur_e,&pre_e)
初始条件:线性表L已存在。
操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,否则操作失败,pre_e无定义
NextElem(L,cur_e,&next_e)
初始条件:线性表L已存在。
操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继,否则操作失败,next_e无定义。
ListInsert(&L,i,e)
初始条件:线性表L已存在,1≤i≤ListLength(L)+1。
操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1。
ListDelete(&L,i,&e)
初始条件:线性表L已存在且非空,1≤i≤ListLength(L)。
操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1。
ListTraverse(L,visit())
初始条件:线性表L已存在。
操作结果:依次对L的每个数据元素调用函数visit()。一旦visit()失败,则操作失败。
}ADT List
6.抽象数据类型
类的基础:抽象数据类型 抽象数据类型(ADT, abstract data type)是指一些数据以及对这些数据所进行的操作的集合。
这些操作既向程序的其余部分描述了这些数据是怎么样的,也允许程序的其余部分改变这些数据。“抽象数据类型”概念中“数据”一词的用法有些随意。
一个ADT可能是一个图形窗体以及所有能影响该窗体的操作;也可以是一个文件以及对这个文件进行的操作;或者是一张保险费率表以及相关操作等等。 要想理解面向对象编程,首先要理解ADT。
不懂ADT的程序员开发出来的类只是名义上的“类”而已——实际上这种“类”只不过就是把一些稍有点儿关系的数据和子程序堆在一起。然而在理解ADT之后,程序员就能写出在一开始很容易实现、日后也易于修改的类来。
传统的编程教科书在讲到抽象数据类型时,总会用一些数学中的事情打岔。这些书往往会像这么写:“你可以把抽象数据类型想成一个定义有一组操作的数学模型。”
这种书会给人一种感觉,好像你从不会真正用到抽象数据类型似的——除非拿它来催眠。 把抽象数据类型解释得这么空洞是完全丢了重点。
抽象数据类型可以让你像在现实世界中一样操作实体,而不必在低层的实现上摆弄实体,这多令人兴奋啊。你不用再向链表中插入一个节点了,而是可以在电子表格中添加一个数据单元格,或向一组窗体类型中添加一个新类型,或给火车模型加挂一节车厢。
深入挖掘能在问题领域工作(而非在底层实现领域工作)的能量吧! Example of the Need for an ADT 需要用到ADT的例子 为了展开讨论,这里先举一个例子,看看ADT在什么情况下会非常有用。有了例子之后我们将继续深入细节探讨。
假设你正在写一个程序,它能用不同的字体、字号和文字属性(如粗体、斜体等)来控制显示在屏幕上的文本。程序的一部分功能是控制文本的字体。
如果你用一个ADT,你就能有捆绑在相关数据上的一组操作字体的子程序——有关的数据包括字体名称、字号和文字属性等。这些子程序和数据集合为一体,就是一个ADT。
如果不使用ADT,你就只能用一种拼凑的方法来操纵字体了。举例来说,如果你要把字体大小改为12磅(point),即高度碰巧为16个像素(pixel),你就要写类似这样的代码: currentFont.size = 16 如果你已经开发了一套子程序库,那么代码可能会稍微好看一些: currentFont.size = PointsToPixels(12) 或者你还可以给该属性起一个更特定的名字,比如说: currentFont.sizeOnPixels = PointsToPixels(12) 但你是不能同时使用currentFont.sizeInPixels和currentFont.sizeInPoints,因为如果同时使用这两项数据成员,currentFont就无从判断到底该用哪一个了。
而且,如果你在程序的很多地方都需要修改字体的大小,那么这类语句就会散布在整个程序之中。 如果你需要把字体设为粗体,你或许会写出下面的语句,这里用到了一个逻辑or运算符和一个16进制常量0x02: currentFont.attribute = CurrentFont.attribute or 0x02 如果你够幸运的话,也可能代码会比这样还要干净些。
但使用拼凑方法的话,你能得到的最好结果也就是写成这样: currentFont.attribute = CurrentFont.attribute or BOLD 或者是这样: currentFont.bold = True 就修改字体大小而言,这些做法都存在一个限制,即要求调用方代码直接控制数据成员,这无疑限制了currentFont的使用。 如果你这么编写程序的话,程序中的很多地方就会到处充斥着类似的代码。
Benefits of Using ADTs 使用ADT的益处 问题并不在于拼凑法是种不好的编程习惯。而是说你可以采用一种更好的编程方法来替代这种方法,从而获得下面这些好处: 可以隐藏实现细节 把关于字体数据类型的信息隐藏起来,意味着如果数据类型发生改变,你只需在一处修改而不会影响到整个程序。
例如,除非你把实现细节隐藏在一个ADT中,否则当你需要把字体类型从粗体的第一种表示变成第二种表示时,就不可避免地要更改程序中所有设置粗体字体的语句,而不能仅在一处进行修改。把信息隐藏起来能保护程序的其余部分不受影响。
即使你想把在内存里存储的数据改为在外存里存储,或者你想把所有操作字体的子程序用另一种语言重写,也都不会影响程序的其余部分。 改动不会影响到整个程序 如果想让字体更丰富,而且能支持更多操作(例如变成小型大写字母、变成上标、添加删除线等)时,你只需在程序的一处进行修改即可。
这一改动也不会影响到程序的其余部分。 让接口能提供更多信息 像currentFont.size = 16这样的语句是不够明确的,因为此处16的单位既可能是像素也可能是磅。
语句所处的上下文环境并不能告诉你到底是哪一种单位。把所有相似的操作都集中到一个ADT里,就可以让你基于磅数或像素数来定义整个接口,或者把二者明确地区分开,从而有助于避免混淆。
更容易提高性能 如果你想提高操作字体时的性能,就可以重新编写出一些更好的子程序,而不用来回修改整个程序。 让程序的正确性更显而易见 验证像currentFont.attribute = current- Font.attribute or 0x02这样的语句是否正确是很枯燥的,你可以替换成像currentFont.SetBoldOn()这样的语句,验证。
7.数据结构 抽象数据类型是什么
这两个概念,尤其是第一个都是特别抽象的概念,没什么具体可对应的实体可以给你举例,我就粘贴复制了,说说我的理解吧。
数据结构呢,我们总是为了完成一个功能或者目的写程序,但不管什么程序、代码实际上都是一些指令的集合,说白了就是在描述“怎么做”,而光知道怎么做还只是问题的一半,还要知道“做什么”,也就是刚才那些指令的对象是谁,自然肯定是相关的数据,比如说学生信息管理中,指令是增加学生,那他的对象就是学生信息这种数据,指令是成绩统计,那对象就是学生的成绩数据,而在我们的程序中,数据也必须要有一种很明确的组织表示方式,只要这样我们才能在这种具体明确的实体上编写指令,比如说学生数据可以定义为一个多维的数组,只有这样我们再写增加学生时,才能知道具体增加就是增加一个数组元素并未其赋值。所以数据结构就是相互之间有联系的具有某种组织方式的数据集合。
抽象数据类型相比较数据结构要具体一些,我们光有了数据结构还不够,因为数据是各种各样的,对于不同数据,我们能采取的方法也不一样,比如说学生数据可以增减,成绩数据可以进行算数运算,但是为什么说抽象呢,也就说他并不是具体整型还是字符型这种基本类型,而是我们根据我们要解决的实际问题,对应现实世界所描述的一种和现实世界中的实体对应的数据类型,而且这种抽象的数据类型还包括能够对于他实行的操作,比如说我们定义一种数据类型叫“学生”,具体的数据我可以定义一中类似表的结构存储,而且还要定义一些操作,比如说添加学生,删除学生,这两部分就共同组成了“学生”这个抽象的数据类型。
不知你明白没?