实验2:栈和队列的基本操作实现及其应用
一、实验目的
1、 熟练掌栈和队列的结构特点,掌握栈和队列的顺序存储和链式存储结构和实现。
2、 学会使用栈和队列解决实际问题。
二、实验内容
1、自己确定结点的具体数据类型和问题规模:
分别建立一个顺序栈和链栈,实现栈的压栈和出栈操作。
分别建立一个顺序队列和链队列,实现队列的入队和出队操作。
2、设计算法并写出代码,实现一个十进制数转换成2进制数。
3、选做题(*)
设计一个模拟饭堂排队打饭管理软件,实现“先来先打饭”的排号叫号管理。
三、实验步骤
1、依据实验内容分别说明实验程序中用到的数据类型的定义;
2、相关操作的算法表达;
3、完整程序;
4、总结、运行结果和分析。
5、总体收获和不足,疑问等。
(1)
建立一个顺序栈实现栈的压栈和出栈操作:
#ifndef SeqStack_H //避免重复包含SeqStack.h头文件
#define SeqStack _H
const int StackSize=10; //栈最多有10个元素
template<class DataType> //定义模板类SeqStack
class SeqStack
{
public:
SeqStack(); //构造函数,栈的初始化
~SeqStack(){} //析构函数
void Push(DataType x); //将元素x入栈
DataType Pop(); //将栈顶元素弹出
DataType GetTop();
int Empty(); //取栈顶元素(并不删除)
private:
DataType data[StackSize]; //存放栈顶元素的数组
int top; //栈顶指针,指示栈顶元素在数组中的下标
};
#endif
#include"SeqStack.h" //引入类SeqStack的声明
//以下是类SeqStack的成员函数定义
template<class DataType>
SeqStack<DataType>::SeqStack() //初始化一个空栈,将栈顶指针top置为-1
{
top=-1;
}
template<class DataType>
void SeqStack<DataType>::Push(DataType x) //入栈操作
{
if(top==StackSize-1)throw"上溢";
top++; //在栈中插入一个元素,将栈顶指针top加1
data[top]=x;
}
template<class DataType>
DataType SeqStack<DataType>::Pop() //出栈操作
{
DataType x;
if(top==-1)throw"下溢";
x=data[top--]; //取出栈顶元素,将栈顶指针top减1
return x;
}
template<class DataType>
DataType SeqStack<DataType>::GetTop() //取栈顶元素
{
if(top!=-1)
return data[top];
}
template<class DataType>
int SeqStack<DataType>::Empty()
{
if(top==-1) return 1; //判空操作,栈为空返回1;非空返回0
else return 0;
}
#include<iostream> //引入输入输出流
using namespace std;
#include"SeqStack.cpp" //引入类SeqStack成员函数定义
//以下是主函数
void main()
{
SeqStack<int>S; //创建模板类的实例
if(S.Empty())
cout<<"栈为空"<<endl;
else
cout<<"栈非空"<<endl;
cout<<"对15和10执行入栈操作"<<endl;
S.Push(15);
S.Push(10);
cout<<"栈顶元素为:"<<endl; //取栈顶元素
cout<<S.GetTop()<<endl;
cout<<"执行一次出栈操作"<<endl;
S.Pop(); //执行出栈操作
cout<<"栈顶元素为:"<<endl;
cout<<S.GetTop()<<endl;
}
运行结果:
建立一个链栈,实现栈的压栈和出栈操作:
#include<iostream>
using namespace std;
struct Node
{
int data;
Node *next;
};
const int StackSize=10;
class LinkStack
{
public:
LinkStack(){top=NULL;}
~LinkStack();
void Push(int x);
int Pop();
int GetTop()
{
if(top!=NULL)
return top->data;
}
int Empty()
{if(top==NULL)
return 1;
else
return 0;
}
private:
Node *top;
};
void LinkStack::Push(int x)
{
Node *s;
s=new Node;s->data=x; //申请一个数据域为x的结点s
s->next=top;top=s; //将结点s插在栈顶
}
int LinkStack::Pop()
{
int x;
Node *p;
if(top==NULL)throw"下溢";
x=top->data;p=top; //暂存栈顶元素
top=top->next; //将栈顶结点摘链
delete p;
return x;
}
LinkStack::~LinkStack()
{
while(top!=NULL) //释放每一个结点的存储空间
{
Node *q;
q=top; //暂存被释放结点
top=top->next; //top指向被释放结点的下一个结点
delete q;
}
}
int main()
{
int i=15,m=10;
LinkStack S;
if(S.Empty())
cout<<"栈为空"<<endl;
else
cout<<"栈非空"<<endl;
cout<<"对15和10执行入栈操作"<<endl;
S.Push(15);
S.Push(10);
cout<<"栈顶元素为:"<<endl;
cout<<S.GetTop()<<endl;
cout<<"执行一次出栈操作"<<endl;
S.Pop();
cout<<"栈顶元素为:"<<endl;
cout<<S.GetTop()<<endl;
return 0;
}
运行结果:
(2)
建立一个顺序队列,实现队列的入队和出队操作
以下代码采用工程多文件形式
#ifndef CirQueue_H //避免重复包含CirQueue.h头文件
#define CirQueue_H
const int QueueSize=100; //定义存储队列元素的数组的最大长度
template<class DataType>//定义模板类
class CirQueue
{
public:
CirQueue(){front=rear=QueueSize-1;} //构造函数,初始化一个空队列
~CirQueue(){} //析构函数
void EnQueue(DataType x); //将元素x入队
DataType DeQueue(); //出队操作,将队头元素出队
DataType GetQueue(); //取队头元素(并不删除)
int Empty() //判断队列是否为空
{if(front==rear)
return 1;
else return 0;
}
private:
DataType data[QueueSize]; //存放队列元素的数组
int front,rear; //队头和队尾指针
};
#endif;
#include"CirQueue.h" //引入类CirQueue的声明
//以下定义CirQueue的成员函数
template<class DataType>
void CirQueue<DataType>::EnQueue(DataType x) //入队算法
{
if((rear+1)%QueueSize==front) throw"上溢";
rear=(rear+1)%QueueSize; //队尾指针在循环意义下加1
data[rear]=x;
}
template<class DataType>
DataType CirQueue<DataType>::DeQueue() //出队算法
{
if(rear==front)throw"下溢";
front=(front+1)%QueueSize; //队头指针在循环意义下加1
return data[front]; //读取并返回出队前的队头元素
}
template<class DataType>
DataType CirQueue<DataType>::GetQueue() //读取队头元素算法
{ int i;
if(rear==front) throw"下溢";
i=(front+1)%QueueSize;
return data[i];
}
#include<iostream>
using namespace std;
#include"CirQueue.cpp" //引入类CirQueue的数据函数成员
//以下是主函数
void main()
{
CirQueue<int>Q; //创建模板类的实例
if(Q.Empty())
cout<<"队列为空"<<endl;
try
{
Q.EnQueue(10); //入队操作
Q.EnQueue(15);
}
catch(char* wrong)
{
cout<<wrong<<endl;
}
cout<<"查看对头元素:"<<endl;
cout<<Q.GetQueue()<<endl; //读队头元素
cout<<"执行出队操作:"<<endl; //出队操作
try
{
Q.DeQueue();
}
catch(char*wrong)
{
cout<<wrong<<endl;
}
cout<<"查看队头元素:"<<endl;
cout<<Q.GetQueue()<<endl;
}
运行结果:
建立一个链队列,实现队列的入队和出队操作
以下代码采用工程多文件形式
#ifndef LinkQueue_H //避免重复包含LinkQueue.h头文件
#define LinkQueue_H
//以下定义链队列的结点
template<class DataType>
struct Node
{
DataType data;
Node<DataType> *next;
};
template<class DataType>
class LinkQueue
{
public:
LinkQueue(); //构造函数,初始化一个空的链队列
~LinkQueue(); //析构函数,释放链队列中各结点的存储空间
void EnQueue(DataType x); //将元素x入队
DataType DeQueue(); //将队头元素出队
DataType GetQueue(); //取链队列的队头元素
int Empty(); //判断链队列是否为空
private:
Node<DataType> *front,*rear; //队头队尾指针
};
#endif;
#include"LinkQueue.h" //引入类LinkQueue的声明
//以下定义LinkQueue的成员函数
template<class DataType>
LinkQueue<DataType>::LinkQueue()
{
Node<DataType> *s=NULL;
s=new Node<DataType>;
s->next=NULL;
front=rear=s;
}
template<class DataType>
LinkQueue<DataType>::~LinkQueue()
{
Node<DataType> *p=NULL;
while(front!=NULL)
{
p=front->next;
delete front;
front=p;
}
}
template<class DataType>
void LinkQueue<DataType>::EnQueue(DataType x)
{
Node<DataType> *s=NULL;
s=new Node<DataType>;
s->data=x; //申请一个数据域为x的结点s
s->next=NULL;
rear->next=s;rear=s; //将结点s插入到队尾
}
template<class DataType>
DataType LinkQueue<DataType>::DeQueue()
{
Node<DataType> *p=NULL;
int x;
if(rear==front)throw"下溢";
p=front->next;
x=p->data; //暂存队头元素
front->next=p->next; //将队头元素所在结点摘链
if(p->next==NULL)rear=front; //判断出队前队列长度是否为1
delete p;
return x;
}
template<class DataType>
DataType LinkQueue<DataType>::GetQueue()
{
if(front!=rear)
return front->next->data;
}
template<class DataType>
int LinkQueue<DataType>::Empty()
{
if(front==rear)
return 1;
else
return 0;
}
#include<iostream>
using namespace std;
#include"LinkQueue.cpp" //引入类LinkQueue的数据函数成员
//以下是主函数
void main()
{
LinkQueue<int>Q; //创建模板类的实例
if(Q.Empty())
cout<<"队列为空"<<endl;
try
{
Q.EnQueue(10); //入队操作
Q.EnQueue(15);
}
catch(char* wrong)
{
cout<<wrong<<endl;
}
cout<<"查看对头元素:"<<endl;
cout<<Q.GetQueue()<<endl; //读队头元素
cout<<"执行出队操作:"<<endl; //出队操作
try
{
Q.DeQueue();
}
catch(char*wrong)
{
cout<<wrong<<endl;
}
cout<<"查看队头元素:"<<endl;
cout<<Q.GetQueue()<<endl;
}
运行结果:
(3)
设计算法并写出代码,实现一个十进制数转换成2进制数
#include<iostream>
using namespace std;
const int StackSize=10;
template<class DataType>
class SeqStack
{
public:
SeqStack();
~SeqStack(){}
void Push(DataType x);
DataType Pop();
void Decimaltor(int num,int r);
private:
DataType data[StackSize];
int top;
};
template<class DataType>
SeqStack<DataType>::SeqStack()
{
top=-1; //初始化一个栈
}
template<class DataType> //入栈算法
void SeqStack<DataType>::Push(DataType x)
{
if(top==StackSize-1)throw"上溢";
top++;
data[top]=x;
}
template<class DataType> //出栈算法
DataType SeqStack<DataType>::Pop()
{
DataType x;
if(top==-1)throw"下溢";
x=data[top--];
return x;
}
template<class DataType>
void SeqStack<DataType>::Decimaltor(int num,int r) //进制转换算法
{
int k;
top=-1;
while(num!=0)
{
k=num%r; //得到余数
Push(k);
num=num/r; //得到商
}
while(top!=-1)
{
cout<<Pop();
}
}
int main()
{
int r,num;
SeqStack<int>S;
cout<<"请输入一个十进制的数字:";
cin>>num;
r=2;
cout<<"转换成2进制的数为:";
S.Decimaltor(num,r);
cout<<endl;
return 0;
}
运行结果: