(一二〇)抽象数据类型
2016-01-19 00:55
155 查看
抽象数据类型(abstract data type, ADT),是以通用的方式描述数据类型,而没有引入语言或实现细节。
程序员常常通过定义类,来表示更通用的概念,而对于抽象数据类型,使用类是一种非常好的方式。
当类概念使用ADT方法时,一般是这样做:
①私有部分必须表示数据存储的方式。例如,可以使用常规数组、动态分配数组或更高级的数据结构(如链表);
②公有接口应隐藏数据表示,而以通用的术语来表达,如创建栈、压入等。
例如代码,这是一个栈的表示方式(注意注释):
总结:
①Stack::push()函数,是将内容放置在私有成员的items数组中,然后通过更改top的值,移动指针。
②调用isfull()和isempty()函数,可以检测这里的栈是否已满。
③top用于指向下一个放置新成员的位置。假如当前有0个成员,他指向0(因为items[0]是空的),有2个成员,他指向2(因为items[0]和items[1]有内容,而items[2]是空的)。
④items[Max]这个数组,用于储存数据;
⑤Item这个类型名,实际上是unsigned long的别名。
⑥push()和pop()函数,分别对应的是放置和取出。并返回是否成功,参数是放置和取出的对象,因此用的是引用。
⑦取出时,实际上并没有删除数组成员的数据,而是改变指向的位置(top的值),假如下一次放置新数据,那么就会覆盖之前的。
⑧默认构造函数使得创建一个新的对象时,其top为0(即指向最初的位置)。
⑨由于Item是unsigned long的别名,因此他一般用作储存整型的数据(浮点类型可能会出现丢失数据的问题。
下面是一个添加了显示名字,并进行实际应用的代码:
输出:
程序员常常通过定义类,来表示更通用的概念,而对于抽象数据类型,使用类是一种非常好的方式。
当类概念使用ADT方法时,一般是这样做:
①私有部分必须表示数据存储的方式。例如,可以使用常规数组、动态分配数组或更高级的数据结构(如链表);
②公有接口应隐藏数据表示,而以通用的术语来表达,如创建栈、压入等。
例如代码,这是一个栈的表示方式(注意注释):
typedef unsigned long Item; //Item作为unsigned long的别名 class Stack { private: enum {Max=5}; //创建枚举常量 Item items[Max]; //Item是unsigned long的别名,见上面 int top; public: Stack(); bool isempty()const; //用于检测是否为空 bool isfull()const; //是否为满 bool push(const Item&item); //放入 bool pop(Item&item); //取出 }; Stack::Stack() //默认构造函数,初始化top为0,top用于计数当前指针指向数组下一次填充时的位置(即如果有一个成员,为items[0],此时top=1 { top = 0; } bool Stack::isempty()const //调用函数,询问是否为空,如果top=0(指向0号位置,说明数组里没有东西),那么top==0为真(返回true),如果top>0(说明数组里至少有一个东西),那么top==0为假(返回false)。 { return top == 0; } bool Stack::isfull()const //调用函数,询问是否满了。如果top=5(说明0~4都有成员),于是top==Max为真(返回true,这里表示满了)相反,则返回false,说明没满 { return top == Max; } bool Stack::push(const Item&item) //调用函数,用于放置 { if (top < Max) //如果没满(原理上面已经解释) { items[top++] = item; //新内容被放置到items数组里,位置为top(因为top指向新内容放置的数组位置),然后top+1 return true; //返回true,说明放置成功 } else return false; //否则返回false,说明放置失败 } bool Stack::pop(Item&item) { if (top > 0) //如果top>0,说明至少有一个元素 { item = items[--top]; //传递的参数等于top-1后(也就是说上一次放置的位置),相当于把里面的内容取出,并赋值给传递的参数(注意,参数是引用) return true; //返回true,说明取出成功 } else return false; //否则返回false,取出失败 }
总结:
①Stack::push()函数,是将内容放置在私有成员的items数组中,然后通过更改top的值,移动指针。
②调用isfull()和isempty()函数,可以检测这里的栈是否已满。
③top用于指向下一个放置新成员的位置。假如当前有0个成员,他指向0(因为items[0]是空的),有2个成员,他指向2(因为items[0]和items[1]有内容,而items[2]是空的)。
④items[Max]这个数组,用于储存数据;
⑤Item这个类型名,实际上是unsigned long的别名。
⑥push()和pop()函数,分别对应的是放置和取出。并返回是否成功,参数是放置和取出的对象,因此用的是引用。
⑦取出时,实际上并没有删除数组成员的数据,而是改变指向的位置(top的值),假如下一次放置新数据,那么就会覆盖之前的。
⑧默认构造函数使得创建一个新的对象时,其top为0(即指向最初的位置)。
⑨由于Item是unsigned long的别名,因此他一般用作储存整型的数据(浮点类型可能会出现丢失数据的问题。
下面是一个添加了显示名字,并进行实际应用的代码:
//1.h 头文件,用于储存类定义 #include<string> #pragma once typedef unsigned long Item; //Item作为unsigned long的别名 struct shuiguo { std::string name; unsigned long m; }; class Stack { private: enum { Max = 5 }; //创建枚举常量 std::string name[Max]; Item items[Max]; //Item是unsigned long的别名,见上面 int top; public: Stack(); bool isempty()const; //用于检测是否为空 bool isfull()const; //是否为满 bool push(const shuiguo&); //放入 bool pop(shuiguo&); //取出 }; //1.cpp 主程序所在源代码文件 #include<iostream> #include<string> #include<Windows.h> #include"1.h" int main() { using namespace std; Stack chuwugui; //创建对象储物柜 cout << "这里是一个储物箱,你是否要存/取东西呢?" << endl; cout << "a.存\tp.取\tq.退出\n我的选择是:"; char choice; while (cin >> choice&&choice != 'q') { while (!isalpha(choice)) //如果输入的不是字母,清除输入缓存,并提示重新输入,然后重新开始循环 { cout << "请输入a.存\tp.取\tq.退出"; cin.sync(); continue; } cin.sync(); //清除输入缓存,只读取第一个输入的字母 switch (choice) //根据输入的不同,执行不同的选项 { case 'a': //输入大写小写的a都是这里 case 'A': if (chuwugui.isfull()) //如果满的话,返回提示信息 { cout << "已经满啦!无法继续存放东西了,你需要取出一些东西才可以。" << endl; break; } else //否则可以存放东西 { shuiguo one; //创建结构,用于存储存放的东西 cout << "请输入你要存放的东西的名称:"; getline(cin, one.name); cout << "请输入你要存放的东西的数量:"; cin >> one.m; cin.sync(); //清除输入缓存,防止干扰 if (chuwugui.push(one)) { cout << "存放成功!" << one.name << " 共计 " << one.m << " 个已经被放入储物柜啦!" << endl; break; } else { cout << "由于某种未知的原因,存放失败了。。。。" << endl; break; } } case 'p': case 'P': if (chuwugui.isempty()) { cout << "很抱歉,储物柜里面已经空空如也了,你不可能再从里面取出什么东西了。" << endl; cout << "等等!你难道要抢走这个萌萌哒的储物箱吗?!警察叔叔!!!~~~" << endl; break; } else { shuiguo one; cout << "现在帮你取东西~~亲~请稍微等待一秒钟。。。" << endl; Sleep(1000); if (chuwugui.pop(one)) { cout << "取出来啦!" << endl; cout << "取出来的东西是 " << one.name << " ,一共有 " << one.m << " 个~~~喏!给你!" << endl; if (chuwugui.isempty()) { cout << "另外呢~~不得不告诉你一声,储物柜里面已经空空如也啦~~" << endl; break; } break; } else { cout << "因为某种未知的错误,什么都没取出来!怎么会这样?" << endl; break; } } default:cout << "可以输入 a 或者 p 或者 q 嘛?你乱输入的话,我是不会知道你想干嘛的!" << endl; break; } cout << endl; cout << "口←一个萌萌哒的储物箱,你是否要存/取东西呢?" << endl; cout << "a.存\tp.取\tq.退出\n我的选择是:"; } cout << endl << "Bye~~~" << endl; system("pause"); return 0; } //2.cpp 存放类的成员函数定义 #include<iostream> #include<string> #include"1.h" Stack::Stack() //默认构造函数,初始化top为0,top用于计数当前指针指向数组下一次填充时的位置(即如果有一个成员,为items[0],此时top=1 { top = 0; } bool Stack::isempty()const //调用函数,询问是否为空,如果top=0(指向0号位置,说明数组里没有东西),那么top==0为真(返回true),如果top>0(说明数组里至少有一个东西),那么top==0为假(返回false)。 { return top == 0; } bool Stack::isfull()const //调用函数,询问是否满了。如果top=5(说明0~4都有成员),于是top==Max为真(返回true,这里表示满了)相反,则返回false,说明没满 { return top == Max; } bool Stack::push(const shuiguo&x) //调用函数,用于放置 { if (top < Max) //如果没满(原理上面已经解释) { name[top] = x.name; items[top++] = x.m; //新内容被放置到items数组里,位置为top(因为top指向新内容放置的数组位置),然后top+1 return true; //返回true,说明放置成功 } else return false; //否则返回false,说明放置失败 } bool Stack::pop(shuiguo&x) { if (top > 0) //如果top>0,说明至少有一个元素 { x.m = items[--top]; //传递的参数等于top-1后(也就是说上一次放置的位置),相当于把里面的内容取出,并赋值给传递的参数(注意,参数是引用) x.name = name[top]; return true; //返回true,说明取出成功 } else return false; //否则返回false,取出失败 }
输出:
这里是一个储物箱,你是否要存/取东西呢? a.存 p.取 q.退出 我的选择是:a 请输入你要存放的东西的名称:苹果 请输入你要存放的东西的数量:1 存放成功!苹果 共计 1 个已经被放入储物柜啦! 口←一个萌萌哒的储物箱,你是否要存/取东西呢? a.存 p.取 q.退出 我的选择是:a 请输入你要存放的东西的名称:梨子 请输入你要存放的东西的数量:5 存放成功!梨子 共计 5 个已经被放入储物柜啦! 口←一个萌萌哒的储物箱,你是否要存/取东西呢? a.存 p.取 q.退出 我的选择是:A 请输入你要存放的东西的名称:香 蕉 请输入你要存放的东西的数量:3 存放成功!香 蕉 共计 3 个已经被放入储物柜啦! 口←一个萌萌哒的储物箱,你是否要存/取东西呢? a.存 p.取 q.退出 我的选择是:p 现在帮你取东西~~亲~请稍微等待一秒钟。。。 取出来啦! 取出来的东西是 香 蕉 ,一共有 3 个~~~喏!给你! 口←一个萌萌哒的储物箱,你是否要存/取东西呢? a.存 p.取 q.退出 我的选择是:p 现在帮你取东西~~亲~请稍微等待一秒钟。。。 取出来啦! 取出来的东西是 梨子 ,一共有 5 个~~~喏!给你! 口←一个萌萌哒的储物箱,你是否要存/取东西呢? a.存 p.取 q.退出 我的选择是:p 现在帮你取东西~~亲~请稍微等待一秒钟。。。 取出来啦! 取出来的东西是 苹果 ,一共有 1 个~~~喏!给你! 另外呢~~不得不告诉你一声,储物柜里面已经空空如也啦~~ 口←一个萌萌哒的储物箱,你是否要存/取东西呢? a.存 p.取 q.退出 我的选择是:p 很抱歉,储物柜里面已经空空如也了,你不可能再从里面取出什么东西了。 等等!你难道要抢走这个萌萌哒的储物箱吗?!警察叔叔!!!~~~ 口←一个萌萌哒的储物箱,你是否要存/取东西呢? a.存 p.取 q.退出 我的选择是:q Bye~~~ 请按任意键继续. . .
相关文章推荐
- 疾病尚需用猛药
- 【C语言】冒泡排序及优化
- (一一九)类作用域
- 学习java的道路
- (一一八)对象数组
- hypervisor on vehicle
- 设计模式之代理模式(二结构型)
- (一一七)this指针
- http servlet服务器和android客户端(二)第一个android客户端
- 单例模式的应用
- 进程间通信(IPC) 之 共享内存 和 闲扯其他一些东西
- python3 crontab 下运行python输出中文失败
- MonoBehaviour继承类及其重要方法
- 敏捷开发解决方案
- 敏捷团队的规范与准则
- 移除未排序链表中的重复结点
- Spark 快速理解
- (一一六)类的构造函数和析构函数
- Think in java浏览一
- hdu1010 Tempter of the Bone