线性表的应用之栈与队列
一、目的要求
1.掌握栈、队列的思想及其存储实现。
2.掌握栈、队列的常见算法的程序实现
二、实验内容
1.采用链式存储实现栈的初始化、入栈、出栈操作。
2.采用顺序存储实现栈的初始化、入栈、出栈操作。
3.采用链式存储实现队列的初始化、入队、出队操作。
4.采用顺序存储实现循环队列的初始化、入队、出队操作。
5.在主函数中设计一个简单菜单,调用上述算法
三、实验说明
1.顺序栈类型定义
const int MAX=20 ; // 栈的最大值
typedef struct
{
ElemType *base;
int top;
} SqStack;
2. 顺序队列类型定义
const int MAX=20 ; // 队列的最大长度
typedef struct
{
ElemType *base;
int front,rear;
} SqQueue;
四、代码
(一)头文件
#pragma once
#include<iostream>
#include<stdlib.h>
using namespace std;
//顺序栈类型定义
const int MAX1 = 20; // 栈的最大值
typedef int ElemType;//元素类型
typedef struct Node
{
ElemType* base;//存放元素的起始指针
int top;//栈顶
} SqStack;//类型名
typedef SqStack* SeqStack;//定义SeqStack为指向结构体类型的指针
//链式栈类型定义
typedef int DataType;
typedef struct LNode
{
DataType data;
struct LNode* next;
};
typedef struct LNode* LinkStack;
//顺序队列类型定义
const int MAX2 = 20; // 队列的最大长度
typedef struct PNode
{
ElemType* base;//指针代表数组首地址
int front;
int rear;//首指针,尾指针用数值表示
};
typedef struct PNode* SqQueue;
//链式队列类型定义
typedef int DataType;
struct Node1
{
DataType data;
struct Node1* next;
};
typedef struct Node1* KNode;
struct Queue
{
KNode f;//队头指针
KNode r;//队尾指针
};
typedef struct Queue* LinkQueue;
/*
顺序栈操作
*/
SeqStack SetStack_Seq()//建立顺序栈
{
SeqStack sstack = (SeqStack)malloc(sizeof(SqStack));//申请结构体空间
sstack->base = (ElemType*)malloc(sizeof(ElemType) * MAX1);//元素空间,以数组表示
cout << "请输入元素以520结束:";
int data;
cin >> data;
sstack->top = -1;//top为栈顶,以第一个元素top为0开始计算
int i = 0;
while (data!=520)
{
sstack->base[i] = data;//赋值
i++;
sstack->top++;//栈顶元素下标加1
cin >> data;
}
return sstack;
}
void ShowStack(SeqStack sstack)
{
cout << "遍历顺序栈:";
for (int i = 0; i <= sstack->top; i++)
{
cout << sstack->base[i]<<" ";
}
}
SeqStack Push_Seq(SeqStack sstack, int x)//输入一个元素进栈
{
sstack->top++;//栈顶下标加1
sstack->base[sstack->top] = x;
return sstack;
}
SeqStack Pop_Seq(SeqStack sstack)//出栈
{
sstack->top= sstack->top-1;//栈顶下标减1
return sstack;
}
/*
链式栈操作
*/
LinkStack SetLink_Stack()//链式栈初始化
{
LinkStack top = (LinkStack)malloc(sizeof(struct LNode));//相当于头结点
if (top != NULL)//非常重要,如果没有这一步,就会出现栈底指针域就不为空
top->next = NULL;
cout << "请输入元素:";
int data;
cin >> data;
while (data!=520)
{
LinkStack PNode = (LinkStack)malloc(sizeof(struct LNode));//建立的元素结点
PNode->data = data;
PNode->next = top->next;//前插法
top->next = PNode;
cin >> data;
}
return top;
}
LinkStack Push_Link(LinkStack top, int x)//进栈-相当于单链表的插入
{
LinkStack q= (LinkStack)malloc(sizeof(struct LNode));//建立进栈元素结点
q->data = x;
q->next = top->next;
top->next = q;
return top;
}
LinkStack Pop_Link(LinkStack top)//出栈-相当于单链表的删除
{
LinkStack q;
q = top->next;
top->next = q->next;
free(q);
return top;
}
void ShowLinkStack(LinkStack top)//遍历链表
{
LinkStack q;
cout << "遍历链式栈:";
for (q=top->next ; q ;q=q->next)
{
cout << q->data << " ";
}
}
/*
顺序队列操作
*/
SqQueue SetQueue()//输入元素建立循环顺序队列
{
SqQueue squeue = (SqQueue)malloc(sizeof(struct PNode));
squeue->front = 0;
squeue->rear = 0;
squeue->base = (ElemType*)malloc(sizeof(ElemType) * MAX2);//存放元素数组的首地址指针
cout << "请输入元素建立顺序队列:";
int data;
cin >> data;
int i = 0;
while (data!=520)
{
squeue->base[i] = data;
i++;
squeue->rear = ((squeue->rear + 1) % (MAX2));//每增加一个元素,尾指针后移一位,当尾指针为max2时,rear又等于0,回到起点开始循环
cin >> data;//尾指针rear始终比i大1
}
return squeue;
}
SqQueue Push_Queue(SqQueue squeue,int x)//进队
{
squeue->base[squeue->rear ] = x;
squeue->rear = ((squeue->rear + 1) % (MAX2));
return squeue;
}
SqQueue Pop_Queue(SqQueue squeue)//出队
{
squeue->front = (squeue->front+1) % MAX2;//首指针加1
return squeue;
}
void ShowQueue(SqQueue squeue)
{
int temp = squeue->front;//下面squeue->front会自增,要保持其值防止下次调用此函数squeue->front是上一次的值
cout << "遍历顺序循环队列为:";
for (squeue->front; squeue->front < squeue->rear; squeue->front++)
{
cout << squeue->base[squeue->front]<<" ";
}
squeue->front = temp;
}
/*
链式队列操作
*/
LinkQueue SetLink_Queue()//建立链式队列
{
LinkQueue lqueue = (LinkQueue)malloc(sizeof(struct Queue));//含有队头队尾的指针的接单
if (lqueue != NULL)
{
lqueue->f = NULL;
lqueue->r = NULL;
}
cout << "请输入元素建立链式队列:";
int data;
cin >> data;
while (data!=520)
{
KNode p=(KNode)malloc(sizeof(struct Node1));
p->data = data;
p->next = NULL;
if (lqueue->f == NULL)//第一个结点特殊处理
{
lqueue->f = p;
lqueue->r = p;
}
else//从第二个开始把尾指针指向新节点p
{
lqueue->r->next = p;
lqueue->r = p;
}
cin >> data;
}
return lqueue;
}
LinkQueue EnQueue_link(LinkQueue lqueue,int x)//进队列,从尾指针进相当于单链表尾部插入元素
{
KNode q=(KNode)malloc(sizeof(struct Node1));
q->data = x;
q->next = NULL;
lqueue->r->next = q;
lqueue->r = q;
return lqueue;
}
LinkQueue DeQueue_link(LinkQueue lqueue)//出队,从头指针删除
{
KNode q;
q = lqueue->f;
lqueue->f = lqueue->f->next;
free(q);
return lqueue;
}
void ShowLink_Queue(LinkQueue lqueue)
{
KNode q;
cout << "遍历链式队列:";
for (q=lqueue->f;q;q=q->next)
{
cout << q->data << " ";
}
}
(二)源文件
/*
实验名称:栈与队列
实验目的:
1.掌握栈、队列的思想及其存储实现。
2.掌握栈、队列的常见算法的程序实现。
实验内容:
1.采用链式存储实现栈的初始化、入栈、出栈操作。
2.采用顺序存储实现栈的初始化、入栈、出栈操作。
3.采用链式存储实现队列的初始化、入队、出队操作。
4.采用顺序存储实现循环队列的初始化、入队、出队操作。
5.在主函数中设计一个简单菜单,调用上述算法。
实验日期:2020/11/28
开发者:每天八杯水
*/
#include<iostream>
#include"栈与队列.h";
using namespace std;
int Out1();//子菜单
/*
顺序栈操作
*/
SeqStack SetStack_Seq();
SeqStack Push_Seq();//类型为SeqStack是返回指针让showstack遍历
SeqStack Pop_Seq();
void ShowStack();
/*
链式栈操作
*/
LinkStack SetLink_Stack();
LinkStack Push_Link();
LinkStack Pop_Link();
void ShowLinkStack();
/*
顺序队列操作
*/
SqQueue SetQueue();
SqQueue Push_Queue();
SqQueue Pop_Queue();
void ShowQueue();
/*
链式队列操作
*/
LinkQueue SetLink_Queue();//建立链式队列
LinkQueue EnQueue_link();
LinkQueue DeQueue_link();
void ShowLink_Queue();
int main()
{
/*
主菜单界面
我设置了一个主菜单四个子菜单界面
实现方法:
1.使用了两个switch进行用户输入不同数字进入不同界面
2.使用循环while判断条件为true或false,true则继续显示菜单界面,false则退出此菜单,若在子菜单false则退出返回到主菜单
*/
bool opt = true;
while (opt == true)
{
cout << "\n\t\t*****************************"<<endl;
cout << "\t\t* 1 顺序存储实现栈 *" << endl;
cout << "\t\t* 2 链式存储实现栈 *" << endl;
cout << "\t\t* 3 顺序存储实现队列 *" << endl;
cout << "\t\t* 4 链式存储实现队列 *" << endl;
cout << "\t\t* 5 退 出 *";
cout << "\n\t\t*****************************" << endl;
cout << "\t\t请选择:";
int a;
cin >> a;
switch (a)
{
case 1:
{
cout << "你选择了顺序存储实现栈" << endl;
/*
进入顺序栈界面
*/
cout << "\n\t\t**************************" << endl;
cout << "\t\t* 欢迎您来到顺序栈的世界 *" << endl;
cout << "\t\t* 请输入元素建立顺序栈 *" << endl;
cout << "\t\t**************************" << endl;
//开始创建顺序栈
SeqStack sstack;
sstack = SetStack_Seq();//创建顺序栈
ShowStack(sstack);//遍历
bool opt1 = true;//顺序栈操作子菜单判断
while (opt1 == true)
{
//创建栈后可选择的操作
cout << "\n\t\t**************************" << endl;
cout << "\t\t* 请您选择操作 *" << endl;
cout << "\t\t* 1 进栈 *" << endl;
cout << "\t\t* 2 出栈 *" << endl;
cout << "\t\t* 3 返回主菜单 *" << endl;
cout << "\t\t**************************" << endl;
cout << "\t\t请选择操作:";
int c;
cin >> c;
switch (c)
{
case 1://进栈操作
cout << "请输入进栈的元素:";
int x;
cin >> x;
ShowStack(Push_Seq(sstack, x));
opt1 =Out1();//为true返回子菜单,为false退出子菜单循环返回主菜单
break;
case 2://出栈操作
ShowStack(Pop_Seq(sstack));
opt1 = Out1();
break;
case 3://返回主菜单
opt1 =false;
break;
default:
cout << "非法输入,请重新输入!" << endl;
break;
}
}
opt =true;
}
break;
case 2:
{
cout << "你选择了链式存储实现栈" << endl;
/*
进入链式栈界面
*/
cout << "\n\t\t**************************" << endl;
cout << "\t\t* 欢迎您来到链式栈的世界 *" << endl;
cout << "\t\t* 请输入元素建立链式栈 *" << endl;
cout << "\t\t**************************" << endl;
//开始创建链式栈
LinkStack LStack;
LStack= SetLink_Stack();//创建链式栈
ShowLinkStack(LStack);//遍历
bool opt1 = true;//链式栈操作子菜单判断
while (opt1 == true)
{
//创建栈后可选择的操作
cout << "\n\t\t**************************" << endl;
cout << "\t\t* 请您选择操作 *" << endl;
cout << "\t\t* 1 进栈 *" << endl;
cout << "\t\t* 2 出栈 *" << endl;
cout << "\t\t* 3 返回主菜单 *" << endl;
cout << "\t\t**************************" << endl;
cout << "\t\t请选择操作:";
int c;
cin >> c;
switch (c)
{
case 1://进栈操作
cout << "请输入进栈的元素:";
int x;
cin >> x;
ShowLinkStack(Push_Link(LStack, x));
opt1 = Out1();//为true返回子菜单,为false退出子菜单循环返回主菜单
break;
case 2://出栈操作
ShowLinkStack(Pop_Link(LStack));
opt1 = Out1();
break;
case 3://返回主菜单
opt1 = false;
break;
default:
cout << "非法输入,请重新输入!" << endl;
break;
}
}
opt = true;
}
break;
case 3:
{
cout << "你选择了顺序存储实现队列" << endl;
/*
进入顺序栈界面
*/
cout << "\n\t\t***************************" << endl;
cout << "\t\t* 欢迎您来到顺序队列的世界 *" << endl;
cout << "\t\t* 请输入元素建立顺序队列 *" << endl;
cout << "\t\t***************************" << endl;
//开始创建顺序队列
SqQueue squeue;
squeue = SetQueue();//创建顺序队列
ShowQueue(squeue);//遍历
bool opt1 = true;//顺序队列操作子菜单判断
while (opt1 == true)
{
//创建队列后可选择的操作
cout << "\n\t\t**************************" << endl;
cout << "\t\t* 请您选择操作 *" << endl;
cout << "\t\t* 1 进队 *" << endl;
cout << "\t\t* 2 出队 *" << endl;
cout << "\t\t* 3 返回主菜单 *" << endl;
cout << "\t\t**************************" << endl;
cout << "\t\t请选择操作:";
int c;
cin >> c;
switch (c)
{
case 1://进队操作
cout << "请输入进队的元素:";
int x;
cin >> x;
ShowQueue(Push_Queue(squeue, x));
opt1 = Out1();//为true返回子菜单,为false退出子菜单循环返回主菜单
break;
case 2://出队操作
ShowQueue(Pop_Queue(squeue));
opt1 = Out1();
break;
case 3://返回主菜单
opt1 = false;
break;
default:
cout << "非法输入,请重新输入!" << endl;
break;
}
}
opt = true;
}
break;
case 4:
{
cout << "你选择了链式存储实现队列" << endl;
/*
进入链式队列界面
*/
cout << "\n\t\t***************************" << endl;
cout << "\t\t* 欢迎您来到链式队列的世界 *" << endl;
cout << "\t\t* 请输入元素建立链式队列 *" << endl;
cout << "\t\t***************************" << endl;
//开始创建链式队列
LinkQueue lqueue;
lqueue = SetLink_Queue();//创建链式队列
ShowLink_Queue(lqueue);//遍历
bool opt1 = true;//链式队列操作子菜单判断
while (opt1 == true)
{
//创建队列后可选择的操作
cout << "\n\t\t**************************" << endl;
cout << "\t\t* 请您选择操作 *" << endl;
cout << "\t\t* 1 进对 *" << endl;
cout << "\t\t* 2 出队 *" << endl;
cout << "\t\t* 3 返回主菜单 *" << endl;
cout << "\t\t**************************" << endl;
cout << "\t\t请选择操作:";
int c;
cin >> c;
switch (c)
{
case 1://进队操作
cout << "请输入进队的元素:";
int x;
cin >> x;
ShowLink_Queue(EnQueue_link(lqueue, x));
opt1 = Out1();//为true返回子菜单,为false退出子菜单循环返回主菜单
break;
case 2://出队操作
ShowLink_Queue(DeQueue_link(lqueue));
opt1 = Out1();
break;
case 3://返回主菜单
opt1 = false;
break;
default:
cout << "非法输入,请重新输入!" << endl;
break;
}
}
opt = true;
}
break;
case 5://退出整个程序
cout << "你选择了退出程序" << endl;
opt =false;
break;
default:
cout << "\t\t非法输入,请重新输入!" << endl;
break;
}
}
cout << "菜单已退出" << endl;
}
/*
每当一个操作执行完后用户可选择回上一层继续操作还是回主菜单选择其他存储结构
*/
int Out1()
{
cout << "\n\t\t*****************" << endl;
cout << "\t\t* 1 返回子菜单 *" << endl;
cout << "\t\t* 2 返回主菜单 *" ;
cout << "\n\t\t*****************" << endl;
cout << "\t\t请选择:";
int b;
cin >> b;
switch (b)
{
case 1:
return true;
break;
case 2:
return false;
break;
default:
cout << "\t\t非法输入,请重新输入!";
return true;
break;
}
}
(三)运行截图
*****************************
* 1 顺序存储实现栈 *
* 2 链式存储实现栈 *
* 3 顺序存储实现队列 *
* 4 链式存储实现队列 *
* 5 退 出 *
*****************************
请选择:1
你选择了顺序存储实现栈
**************************
* 欢迎您来到顺序栈的世界 *
* 请输入元素建立顺序栈 *
**************************
请输入元素以520结束:1 2 3 4 520
遍历顺序栈:1 2 3 4
**************************
* 请您选择操作 *
* 1 进栈 *
* 2 出栈 *
* 3 返回主菜单 *
**************************
请选择操作:2
遍历顺序栈:1 2 3
*****************
* 1 返回子菜单 *
* 2 返回主菜单 *
*****************
请选择:1
**************************
* 请您选择操作 *
* 1 进栈 *
* 2 出栈 *
* 3 返回主菜单 *
**************************
请选择操作:1
请输入进栈的元素:5201314
遍历顺序栈:1 2 3 5201314
*****************
* 1 返回子菜单 *
* 2 返回主菜单 *
*****************
请选择:2
*****************************
* 1 顺序存储实现栈 *
* 2 链式存储实现栈 *
* 3 顺序存储实现队列 *
* 4 链式存储实现队列 *
* 5 退 出 *
*****************************
请选择:2
你选择了链式存储实现栈
**************************
* 欢迎您来到链式栈的世界 *
* 请输入元素建立链式栈 *
**************************
请输入元素:9 8 7 6 5 4 520
遍历链式栈:4 5 6 7 8 9
**************************
* 请您选择操作 *
* 1 进栈 *
* 2 出栈 *
* 3 返回主菜单 *
**************************
请选择操作:1
请输入进栈的元素:5201314
遍历链式栈:5201314 4 5 6 7 8 9
*****************
* 1 返回子菜单 *
* 2 返回主菜单 *
*****************
请选择:1
**************************
* 请您选择操作 *
* 1 进栈 *
* 2 出栈 *
* 3 返回主菜单 *
**************************
请选择操作:2
遍历链式栈:4 5 6 7 8 9
*****************
* 1 返回子菜单 *
* 2 返回主菜单 *
*****************
请选择:2
*****************************
* 1 顺序存储实现栈 *
* 2 链式存储实现栈 *
* 3 顺序存储实现队列 *
* 4 链式存储实现队列 *
* 5 退 出 *
*****************************
请选择:3
你选择了顺序存储实现队列
***************************
* 欢迎您来到顺序队列的世界 *
* 请输入元素建立顺序队列 *
***************************
请输入元素建立顺序队列:11 22 33 44 520
遍历顺序循环队列为:11 22 33 44
**************************
* 请您选择操作 *
* 1 进队 *
* 2 出队 *
* 3 返回主菜单 *
**************************
请选择操作:2
遍历顺序循环队列为:22 33 44
*****************
* 1 返回子菜单 *
* 2 返回主菜单 *
*****************
请选择:1
**************************
* 请您选择操作 *
* 1 进队 *
* 2 出队 *
* 3 返回主菜单 *
**************************
请选择操作:5201314
非法输入,请重新输入!
**************************
* 请您选择操作 *
* 1 进队 *
* 2 出队 *
* 3 返回主菜单 *
**************************
请选择操作:1
请输入进队的元素:5201314
遍历顺序循环队列为:22 33 44 5201314
*****************
* 1 返回子菜单 *
* 2 返回主菜单 *
*****************
请选择:2
*****************************
* 1 顺序存储实现栈 *
* 2 链式存储实现栈 *
* 3 顺序存储实现队列 *
* 4 链式存储实现队列 *
* 5 退 出 *
*****************************
请选择:4
你选择了链式存储实现队列
***************************
* 欢迎您来到链式队列的世界 *
* 请输入元素建立链式队列 *
***************************
请输入元素建立链式队列:01 02 03 04 05 06 520
遍历链式队列:1 2 3 4 5 6
**************************
* 请您选择操作 *
* 1 进对 *
* 2 出队 *
* 3 返回主菜单 *
**************************
请选择操作: 2
遍历链式队列:2 3 4 5 6
*****************
* 1 返回子菜单 *
* 2 返回主菜单 *
*****************
请选择:1
**************************
* 请您选择操作 *
* 1 进对 *
* 2 出队 *
* 3 返回主菜单 *
**************************
请选择操作:1
请输入进队的元素:5201314
遍历链式队列:2 3 4 5 6 5201314
*****************
* 1 返回子菜单 *
* 2 返回主菜单 *
*****************
请选择:2
*****************************
* 1 顺序存储实现栈 *
* 2 链式存储实现栈 *
* 3 顺序存储实现队列 *
* 4 链式存储实现队列 *
* 5 退 出 *
*****************************
请选择:5
你选择了退出程序
菜单已退出
A:\3-数据结构与算法\实验\上机实验报告\实验1:线性表的应用\栈与队列\Debug\栈与队列.exe (进程 20844)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
五、思考总结
1.对于栈与队列的理解加深了,这是第二次敲栈与队列,熟悉了原理,查缺补漏,第一遍不理解的地方也疏通了
2.我的理解栈与队列就是顺序表和单链表的特殊处理;比如顺序栈——本质就是顺序表,只不过我们规定了它只能从尾巴进尾巴出,代码实现改变了一下。再者链式队列——相当于单链表的特殊处理,进队出队本质就是单链表的插入和删除,只是代码规定了只能从尾巴插入就是最后一个元素后面插入,只能从第一个元素删除称为出队。链式栈和顺序队列同理,这样更容易理解一点
3.自此我的数据结构与算法实验1——线性表的应用一共四个应用:顺序表、单向链表、双向链表、栈与队列都完成了一共历时一周,很开心,因延期回校复学晚了的情况下终于把这门课程进度赶上了,下周就要开始实验2了——二叉树的应用,加油加油加油奥利给!
谢谢您的浏览,由于水平有限,很多地方有待提高,若您有更好的建议欢迎留言!————————————每天八杯水