(一二〇)抽象数据类型

抽象数据类型(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的值),假如下一次放置新数据,那么就会覆盖之前的。

 

⑧默认构造函数使得创建一个新的对象时,其top0(即指向最初的位置)。

 

⑨由于Itemunsigned 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~~~
请按任意键继续. . .


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值