3-1 将编号0和1的两个栈存放于一个数组空间V[m]中,栈顶分别处于数组两端。两栈均从两端向中间增长,试编写双栈初始化,判断栈空、栈满、进栈和出栈等算法的函数。双栈数据结构的定义如下:
typedef struct
{
int top[2],bot[2];//栈顶和栈底指针
SElemType *V;//栈数组
int m; //栈最大可容纳元素个数
}DblStack;
#include
using namespace std;
#define MAXSIZE 100
typedef struct{
int top[2],bot[2];
int *V;
int m;
}DblStack;
void InitStack(DblStack &s);
void CheckNull(DblStack s);
void CheckFull(DblStack s);
void Push(DblStack &s,int n);
void Pop(DblStack &s,int n);
int main(){
DblStack s;
int n,choice;
InitStack(s);
CheckNull(s);
cout<<"请输入进栈个数:";
cin>>n;
Push(s,n);
cout<<"请输入出栈个数:";
cin>>n;
Pop(s,n);
CheckFull(s);
return 0;
}
//双栈初始化
void InitStack(DblStack &s){
cout<<"请输入栈长:";
cin>>s.m;
s.bot[0]=0;
s.bot[1]=s.m-1;
s.top[0]=s.bot[0];
s.top[1]=s.bot[1];
cout<<"双栈长度为:"<<s.m<<endl;
}
//判断栈空
void CheckNull(DblStack s){
if(s.top[0]==s.bot[0]&&s.top[1]==s.bot[1]){
cout<<"两个栈都为空"<<endl;
}else if(s.top[0]==s.bot[0]&&s.top[1]!=s.bot[1]){
cout<<"只有第一个栈为空"<<endl;
}else if(s.top[0]!=s.bot[0]&&s.top[1]==s.bot[1]){
cout<<"只有第二个栈为空"<<endl;
}else{
cout<<"两个栈都不为空"<<endl;
}
}
//栈满:两个栈顶相邻
void CheckFull(DblStack s){
if(s.top[1]-s.top[0]==1){
cout<<"栈满了"<<endl;
}else{
cout<<"栈未满"<<endl;
}
}
/*入栈:n为入栈总个数,选择入哪个栈,
如果为1号栈,先输入索引为top[0]值的位置的值,再让top[0]值+1,
如果为2号栈,先输入索引为top[1]值的位置的值,再让top[1]值-1,
接着又判断入哪个栈,重复操作直至入栈总个数达到预定值*/
void Push(DblStack &s,int n){
int e,choice;
for(int i=0;i<n;i++){
cout<<"进哪个栈(1为1号栈,2为2号栈):";
cin>>choice;
if(choice==1){
if(s.top[1]-s.top[0]==1){
cout<<"栈满无法进栈"<<endl;
break;
}else{
cout<<"进1号栈值为:";
cin>>e;
s.V[s.top[0]++]=e;
}
}else{
if(s.top[1]-s.top[0]==1){
cout<<"栈满无法进栈"<<endl;
break;
}else{
cout<<"进2号栈值为:";
cin>>e;
s.V[s.top[1]--]=e;
}
}
}
}
/*出栈:n为出栈总个数,选择出哪个栈,
如果为1号栈,top[0]值先-1,再输出索引为top[0]值的位置的值,
如果为2号栈,top[1]值先+1,再输出索引为top[1]值的位置的值,
接着又判断出哪个栈,重复操作直至出栈总个数达到预定值*/
void Pop(DblStack &s,int n){
int e,choice;
for(int i=0;i<n;i++){
cout<<"出哪个栈(1为1号栈,2为2号栈):";
cin>>choice;
if(choice==1){
if(s.bot[0]==s.top[0]){
cout<<"栈空无法出栈"<<endl;
break;
}else{
e=s.V[--s.top[0]];
cout<<"1号栈出栈为:"<<e<<endl;
}
}else{
if(s.bot[1]==s.top[1]){
cout<<"栈空无法出栈"<<endl;
break;
}else{
e=s.V[++s.top[1]];
cout<<"2号栈出栈为:"<<e<<endl;
}
}
}
}
3-6 假设以带头结点的循环链表表示队列,并且只设一个指针指向队尾元素结点(注意:不设头指针),试编写相应的置空队列、判断队列是否为空、入队和出队等算法
#include
using namespace std;
#define MAXSIZE 100
typedef struct LNode{
int data;
struct LNode *next;
}LNode,*LinkList;
typedef struct{
LinkList rear;
}LinkQueue;
void InitQueue(LinkQueue &q);
void SetNull(LinkQueue &q);
bool CheckNull(LinkQueue q);
void EnQueue(LinkQueue &q,int e);
void DeQueue(LinkQueue &q);
int main(){
LinkQueue q;
InitQueue(q);
EnQueue(q,100);
DeQueue(q);
EnQueue(q,200);
DeQueue(q);
CheckNull(q);
SetNull(q);
CheckNull(q);
return 0;
}
//初始化循环链式队列
void InitQueue(LinkQueue &q){
q.rear=new LNode;
q.rear->next=q.rear;
cout<<"初始化成功"<<endl;
}
//置空队列
void SetNull(LinkQueue &q){
LinkList s;
q.rear=q.rear->next;
while(q.rear!=q.rear->next){
s=q.rear->next;
q.rear->next=s->next;
delete s;
}
cout<<"置空成功"<<endl;
}
//判断空队列:尾指针下一个位置指向尾指针本身
bool CheckNull(LinkQueue q){
if(q.rear->next==q.rear){
cout<<"队列为空"<<endl;
return true;
}else{
cout<<"队列不为空"<<endl;
return false;
}
}
/*入队:在队尾插入新结点,使新结点的指针指向首节点,尾指针指向新结点*/
void EnQueue(LinkQueue &q,int e){
LinkList p;
p->data=e;
p->next=q.rear->next;
q.rear->next=p;
q.rear=p;
cout<<"入队的值为:"<<e<<endl;
}
/*出队:在队头删除结点,判断是否是空队列,若为空就返回信息;
若不是且只有一个结点,就让尾指针指向头指针位置,头指针位置的指针指向尾指针;
若不止一个结点,就让头指针位置的指针指向要出队结点的下一个指针位置;
最后释放出队结点的空间*/
void DeQueue(LinkQueue &q){
LinkList p;
int e;
if(CheckNull(q)){
cout<<"队列为空,不能出队"<<endl;
}else{
p=q.rear->next->next;
e=p->data;
if(p==q.rear){
q.rear=q.rear->next;
q.rear->next=p->next;
}else{
q.rear->next->next=p->next;
}
delete p;
cout<<"出去的值为:"<<e<<endl;
}
}
3-7 假设以数组Q[m]存放循环队列中的元素,同时设置一个标志tag,以tag=0和tag=1来区别在队头指针(front)和队尾指针(rear)相等时,队列状态为“空”还是“满”。试编写与此结构相应的插入(enqueue)和删除(dequeue)算法
#include
using namespace std;
#define m 10
typedef struct{
int *base;
int front;
int rear;
int tag;
}SqQueue;
void InitQueue(SqQueue &s);
void EnQueue(SqQueue &s);
void DeQueue(SqQueue &s);
void CheckFullOrNull(SqQueue s);
int main(){
SqQueue s;
InitQueue(s);
EnQueue(s);
DeQueue(s);
return 0;
}
//初始化循环队列
void InitQueue(SqQueue &s){
s.base=new int[m];
s.front=s.rear=0;
s.tag=0;
}
//入队:队尾插入且队尾下标+1,tag=1队列不为空
void EnQueue(SqQueue &s){
int e;
if(s.tag==1&&s.front==s.rear){
cout<<"队列满了无法入队"<<endl;
}else{
cout<<"输入入队的值:";
cin>>e;
s.base[s.rear]=e;
s.rear=(s.rear+1)%m;
s.tag=1;
}
CheckFullOrNull(s);
}
//出队:队头删除,且队头下标+1,当队尾等于队头下标tag=0队列为空
void DeQueue(SqQueue &s){
int e;
if(s.tag==0&&s.front==s.rear){
cout<<"队列空了无法出队"<<endl;
}else{
e=s.base[s.front];
s.front=(s.front+1)%m;
cout<<"出队的值为:"<<e<<endl;
if(s.rear==s.front){
s.tag=0;
}
}
CheckFullOrNull(s);
}
void CheckFullOrNull(SqQueue s){
if(s.tag==0){
cout<<"队列为空"<<endl;
}else{
cout<<"队列不空"<<endl;
}
}
3-8 如果允许在循环队列的两端都可以进行插入和删除操作。要求:(1)写出循环队列类型定义(2)写出“从队尾删除”和“从队头插入”的算法
#include
using namespace std;
#define m 10
typedef struct{
int *base;
int front;
int rear;
}SqQueue;
//从队头入队
void EnQueue(SqQueue &s){
int e;
if(s.front==(s.rear+1)%m){
cout<<"队列满了无法入队"<<endl;
}else{
cout<<"从队头插入的值:";
cin>>e;
s.base[s.front]=e;
s.front=(s.front-1+m)%m;
}
}
//从队尾出队
void DeQueue(SqQueue &s){
int e;
if(s.front==s.rear){
cout<<"队列空了无法出队"<<endl;
}else{
e=s.base[s.rear];
s.rear=(s.rear-1+m)%m;
cout<<"从队尾删除的值为:"<<e<<endl;
}
}
//初始化循环队列
void InitQueue(SqQueue &s){
s.base=new int[m];
s.front=s.rear=0;
}
void InitQueue(SqQueue &s);
void EnQueue(SqQueue &s);
void DeQueue(SqQueue &s);
int main(){
SqQueue s;
InitQueue(s);
EnQueue(s);
DeQueue(s);
return 0;
}