《数据结构与算法设计》实验报告书之栈的存储结构定义及基本操作
实验项目
栈的存储结构定义及基本操作
实验目的
. 掌握栈的逻辑特征
. 掌握栈顺序存储结构的特点,熟练掌握顺序栈的基本运算
. 熟练掌握栈的链式存储结构定义及基本操作
. 加深对顺序存储数据结构的理解和链式存储数据结构的理解,逐步培养解决实际问题的编程能力
实验内容
(一)基本实验内容:
1)问题描述:
假设以键盘输入的方式输入一个正整数序列:比如x1, x2, x3,…,xn,要求算法实现:当ai≠0时,将ai进栈;当ai=0时,输出栈顶元素并出栈。用栈结构存储所输入的整数序列,并且要求算法的健壮性及能够应对异常情况(如果是顺序要判断栈满栈空,如果是链式栈要判断栈空等)并给出相应的提示系统信息。
试编程实现该程序。
① 输入的形式和输入值的范围:需要用户以键盘输入的方式输入一个正整数序列
② 输出的形式:通过运行程序后将最后的正整数序列输出。
③ 程序所能达到的功能:通过对栈的使用完成对正整数序列输出
④ 测试数据:13个元素 1203405607809
输出为:13579
(二)实现要求:
- 编写函数,实现栈的初始化、入栈、出栈、判断栈空操作。不限顺序栈或者链栈
- 编写函数,实现正整数序列输出的操作。
- 编写一个主函数,在主函数中设计一个简单的菜单,分别调试上述算法。
请遵循“清晰第一,效率第二”的良好编程风格,给与必要的注释说明。
算法设计分析
(一)数据结构的定义
顺序栈,即栈的顺序存储结构,是利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top指示栈顶元素在顺序 栈中的位置。为了能实现实验内容的要求,所以先实现栈的初始化、入栈、出栈、判断栈空操作,并且要求算法的健壮性。在后面使用行编辑函数的时候便于调用,以便更好地实现行编辑的功能。
顺序表存储结构定义为:
/定义顺序栈/
#define maxsize 50
typedef struct
{
int stack[maxsize];
int top;
} seqlist;
(二)总体设计
实验总共包括九个函数:主函数,初始化顺序栈函数,顺序栈栈长函数,入栈函数,打印顺序栈函数,出栈函数,逆序输出函数,行编辑1.0函数(实验要求),行编辑2.0函数(附加题要求)。
主函数:统筹调用各个函数以实现相应功能
Int main()
初始化顺序栈函数:将顺序栈的top初始化为-1
Void seqinit ()
顺序栈栈长函数:返回顺序栈的长度
Int listlength()
入栈函数:将输入的数据传入顺序栈中
Void seqbulid()
打印顺序栈函数:将顺序栈数据打印出来
Void seqprinter ()
出栈函数:实现顺序栈种单个元素的弹出
Void seqdelete ()
逆序打印函数:实现顺序栈的逆序打印
void seqsetter()
行编辑1.0函数(实验要求)
int seqlocate1()
行编辑2.0函数(附加题要求)
int seqlocate2()
(三)各函数的详细设计:
主函数main()
主要就是进行功能的实现。
初始化顺序栈函数seqinit ()
简单的对顺序栈的top进行初始化为-1,不然程序会报错。
顺序栈栈长函数listlength()
直接返回顺序栈的长度l->top+1。
顺序栈入栈函数seqbulid()
实行顺序栈的创建,把输入的数据一个一个存进开辟好空间的顺序栈中,并且顺序栈的top进行加加。
打印顺序栈函数seqprinter ()
就是直接将顺序栈打印出来,不过要注意换行
打印顺序栈函数seqsetter()
就是直接将顺序栈逆序的打印出来,不过要注意换行
顺序栈出栈函数seqdelete ()
元素的出栈,因为是栈,遵循着先进后出的原则,所以栈的出栈就显得比较简单了,直接把最后一个元素弹出即可,先用一个变量保留弹出的元素,之后top–,把弹出的元素return就好了。
行编辑1.0函数(实验要求)
实现以键盘输入的方式输入一个正整数序列:比如x1, x2, x3,…,xn,要求算法实现:当ai≠0时,将ai进栈;当ai=0时,输出栈顶元素并出栈。用栈结构存储所输入的整数序列,并且要求算法的健壮性及能够应对异常情况(如果是顺序要判断栈满栈空,如果是链式栈要判断栈空等)并给出相应的提示系统信息。
行编辑2.0函数(附加题要求)
实现以键盘输入的方式输入一个正整数序列:比如x1, x2, x3,…,xn,要求算法实现:当ai≠0时,将ai进栈;当ai=0时,前一个数字加1。用栈结构存储所输入的整数序列,并且要求算法的健壮性及能够应对异常情况(如果是顺序要判断栈满栈空,如果是链式栈要判断栈空等)并给出相应的提示系统信息。
实验测试结果
实验总结:(100字到200字)
此部分附上主要程序代码和相关的注释说明、调试数据及过程、问题及解决办法。 (最重要)
(1)调试过程中主要遇到哪些问题?是如何解决的?
答:其实顺序栈的难度不大,遇见的问题只有一个,就是打印,因为打印是用while(l->top>=0)实现,里面的l->top–导致栈里面的数全部弹出,导致后面的实验无法进行,所以,转变一种方法,用for或者用一个变量来代替l->top使之减减,这样问题就解决了。
(2)经验和体会
答:还是那句老话,多敲代码自己练习,有时间把链式栈写一遍,增加自己对栈的理解能力。
附录 实验程序代码(该部分请加注释)
/SeqList.h函数代码/
//#ifndef SEQLIST_H_INCLUDED
//#define SEQLIST_H_INCLUDED
/*定义顺序栈*/
#define maxsize 50
typedef struct
{
int stack[maxsize];
int top;//定义顺序栈的栈顶
} seqlist;
/*初始化顺序栈*/
void seqinit(seqlist *l)
{
l->top=-1;//初始化栈顶为-1
}
/*顺序栈栈长函数listlength()*/
int listlength(seqlist *l)
{
return l->top+1;//返回顺序栈的长度
}
/*入栈函数seqbulid()*/
int seqbulid(seqlist *l,int x)
{
l->top++;
if(l->top >= maxsize){//判断栈是否已满
std::cout<<"该顺序栈已满!!"<<std::endl;
return 0;
}
l->stack[l->top]=x;
return 1;
}
/*打印顺序栈函数seqprinter ()*/
void seqprinter(seqlist *l)
{
if(l->top < 0){//判断栈是否为空
std::cout<<"该栈为空"<<std::endl;
return ;
}
for(int i=0;i<=l->top;i++)
{
std::cout<<" "<<l->stack[i];
}
std::cout<<"\n";
}
/*出栈函数seqdelete ()*/
int seqdelete(seqlist *l)
{
int x;
x = l->stack[l->top];//保留被弹出的元素
l->top--;
return x;
}
/*逆序输出*/
void seqsetter(seqlist *l)
{
if(l->top < 0){//判断栈是否为空
std::cout<<"该栈为空"<<std::endl;
return ;
}
for(int i=l->top;i>=0;i--)
{
std::cout<<" "<<l->stack[i];
}
std::cout<<"\n";
}
/*行编辑函数1.0版本seqlocate ()*/
int seqlocate1(seqlist *l)
{
l->top=-1;//清空之前的顺序栈
std::cout<<"请输入行编辑之前的数据:"<<std::endl;
int x;
while(std::cin>>x && x >=0)
{
if(x == 0){//判断该元素是否为零,如为零,则将之前的数弹出
seqdelete(l);
}else{
seqbulid(l,x);
}
}
std::cout<<"行编辑之后的数据:"<<std::endl;
seqprinter(l);
return 1;
}
/*行编辑函数2.0版本seqlocate ()*/
int seqlocate2(seqlist *l)
{
l->top=-1;
std::cout<<"请输入行编辑之前的数据:"<<std::endl;
int x;
while(std::cin>>x && x >=0)
{
if(x == 0){//判断该元素是否为零,如为零,则将之前的数+1
l->stack[l->top]++;
}else{
seqbulid(l,x);
}
}
std::cout<<"行编辑之后的数据:"<<std::endl;
seqprinter(l);
return 1;
}
//#endif // SEQLIST_H_INCLUDED
/主函数代码/
#include <iostream>
#include "SeqList.h"
#include "menu.h"
using namespace std;
int main(){
void operation();
operation();
return 0;
}
void operation(){
seqlist *l = new seqlist;//申请内存空间
seqinit(l);//顺序表的初始化
for(;;){
char n;
int x;
menu();
cin>>n;
switch (n){
case 'a':
seqinit(l);//顺序表的初始化
cout<<"请输入数据:\n";
while(cin>>x && x>=0){
seqbulid(l,x);//入栈
}
break;
case 'b':
cout<<"出栈的数据为:"<<seqdelete(l);//出栈
break;
case 'c':
cout<<"打印的顺序栈为:\n";
seqprinter(l);
break;
case 'd':
cout<<"顺序表逆序之后:\n";
seqsetter(l);
break;
case 'e':
seqlocate1(l);
break;
case 'f':
cout<<"该顺序栈的栈长为:"<<listlength(l)<<"\n";
break;
case 'g':
seqlocate2(l);
break;
case 'h':
cout<<"本次服务到结束,下次再见!!"<<endl;
return ;
default:
cout<<"输入的字符有问题,请重新输入!!";
break;
}
}
}
/menu.h菜单函数代码/
#ifndef MENU_H_INCLUDED
#define MENU_H_INCLUDED
void menu(){
std::cout<<"\n";
std::cout<<" **********************顺序栈的应用**********************\n";
std::cout<<" * *\n";
std::cout<<" * a:入栈 b:出栈 *\n";
std::cout<<" * c:顺序打印栈 d:逆序打印栈 *\n";
std::cout<<" * e:行编辑1.0版本 f:打印顺序栈的长度 *\n";
std::cout<<" * g:行编辑2.0版本 h:退出程序 *\n";
std::cout<<" * *\n";
std::cout<<" ********************************************************\n";
}
#endif // MENU_H_INCLUDED