您的位置:首页 > 其它

(一二〇)抽象数据类型

2016-01-19 00:55 155 查看
抽象数据类型(abstract data type, ADT),是以通用的方式描述数据类型,而没有引入语言或实现细节。

程序员常常通过定义类,来表示更通用的概念,而对于抽象数据类型,使用类是一种非常好的方式。

当类概念使用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~~~
请按任意键继续. . .
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: