数据结构栈与队列

东北林业大学

实验二

实验名称:栈、队列

实验室名称:905

实验台号:18

学生姓名:**

专业班级:2016级计算机科学与技术四班

指导教师:王阿川(教授)

实验日期: 2018-04-25

 

一、实验目的

1.掌握栈、队列的思想及其存储实现。

2.掌握栈、队列的常见算法的程序实现。

二、实验仪器及环境:

    PC计算机;windows 10操作系统、codeblocks17.12;

三、实验内容及结果(按照具体实验题目,按照如下格式书写)

1. 采用链式存储实现栈的初始化、入栈、出栈操作。

存储结构:

typedef int Status;

typedef int SElemType;

typedef struct SNode{

    SElemTypedata;

    structSNode *next;

}SNode,*LinkStack;

程序:

#include<iostream>
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
typedef int SElemType;
typedef struct SNode{
        SElemTypedata;
        structSNode *next;
}SNode,*LinkStack;
//链栈的初始化
Status InitStack (LinkStack &S)
{
     S=NULL;
     return OK;
}
// 链栈的入栈
Status Push(LinkStack &S , SElemType e)
{
        SNode*p = new SNode;
        if(!p)
        {
               returnOVERFLOW;
        }
        p->data= e;
        p->next= S;
        S= p;
        returnOK;
}
//链栈的出栈
Status Pop (LinkStack &S,SElemType &e)
{
        SNode*p;
               if(!S)
                       returnERROR;
               e= S->data;
               p= S;
               S= S->next;
               deletep;
               returnOK;
}
int main()
{
        LinkStacks;
        SElemTypee;
        cout<<"进栈元素依次为:"<<endl;
        if(InitStack(s)==OK)
               for(intj=1;j<=25;j++)
               {
                       Push(s,j);
                       cout<<j<<"  ";
               }
        cout<<endl<<"依次弹出的栈顶元素为:"<<endl;
        while(Pop(s,e)== OK)
        {
               cout<<e<<"  ";
        }
        return0;
}

2.采用链式存储实现栈的初始化、入栈、出栈操作。

存储结构:

typedefint Status;

typedefint SElemType;

typedefstruct{

         SElemType *base;

         SElemType *top;

         int stacksize;

}SqStack;

程序;

#include<iostream>
#include<stdlib.h>
usingnamespace std;
#defineOK 1
#defineERROR 0
#defineOVERFLOW -2
#defineMAXSIZE  100
typedefint Status;
typedefint SElemType;
typedefstruct{
         SElemType *base;
         SElemType *top;
         int stacksize;
}SqStack;
//顺序栈的初始化
StatusInitStack(SqStack &S)
{
         S.base = new SElemType[MAXSIZE];
         if(!S.base)
                  exit (OVERFLOW);
         S.top = S.base;
         S.stacksize = MAXSIZE;
         return OK;
}
//顺序栈的入栈
StatusPush(SqStack &S,SElemType &e)
{
         if(S.top-S.base==S.stacksize)
                  return ERROR;
         *(S.top++) = e; //元素e压入栈顶,栈顶指针加1
         return OK;
}
//顺序栈的出栈
StatusPop(SqStack &S,SElemType &e)
{
         if(S.base == S.top)
                  return ERROR;
         e = *(--S.top); //栈顶指针减1,将栈顶元素赋给e
         return OK;
}
intmain()
{
         SqStack s;
         SElemType e;
         SElemType t;
         cout<<"进栈元素依次为:"<<endl;
         if(InitStack(s)==OK)
                  for(int j=1;j<=12;j++)
                  {
                          Push(s,j);
                          cout<<j<<"";
                  }
         cout<<endl<<"依次弹出的栈顶元素为:"<<endl;
         while(s.base!=s.top)
         {
                  Pop(s,t);
                  cout<<t<<"";
         }
         return 0;
}

3.采用链式存储实现队列的初始化、入队、出队操作。

存储结构:

typedefint QElemType;

typedefint Status;

typedefstruct QNode{

         QElemType data;

         QNode *next;

}QNode,*QueuePtr;

typedefstruct{

         QueuePtr front;

         QueuePtr rear;

}LinkQueue;

程序:

#include<iostream>
usingnamespace std;
#defineOK 1
#defineERROR 0
#defineOVERFLOW -2
typedefint QElemType;
typedefint Status;
typedefstruct QNode{
         QElemType data;
         QNode *next;
}QNode,*QueuePtr;
typedefstruct{
         QueuePtr front;
         QueuePtr rear;
}LinkQueue;
 
//链队的初始化
StatusInitQueue(LinkQueue &Q)
{
         Q.front = new QNode;
         if(Q.front == NULL)
         {
                  return OVERFLOW;
         }
         Q.front->next = NULL;
         Q.rear = Q.front;
         return OK;
}
//链队的入队
StatusEnQueue(LinkQueue &Q,QElemType e)
{
         QNode *p = new QNode;
         if(p == NULL)
         {
                  return OVERFLOW;
         }
         p->data = e;
         p->next = NULL;
         Q.rear->next = p;
         Q.rear = p;       // 修改队尾指针
         return OK;
}
//链队的出队
StatusDeQueue(LinkQueue &Q,QElemType &e)
{
         if(Q.front == Q.rear)
         {
                  return ERROR;
         }
         QNode *p = Q.front->next;
         e = p->data;
         Q.front->next = p->next;
         if(Q.rear == p)
         {
                  Q.rear = Q.front;
         }
         delete p;
         return OK;
}
intmain()
{
         LinkQueue Q;
         QElemType e;
         cout<<"进链队的元素依次为:"<<endl;
         if(InitQueue(Q)==OK)
                  for(int j=1;j<=30;j++)
                  {
                          EnQueue(Q,j);
                          cout<<j<<"";
                  }
         cout<<endl<<"依次出链队的元素为:"<<endl;
         while(DeQueue(Q,e) == OK)
         {
                  cout<<e<<"";
         }
         return 0;
}

4.采用顺序存储实现循环队列的初始化、入队、出队操作。

存储结构:

typedef int QElemType;

typedef int Status;

typedef struct{

   QElemType *base;

   int front;      //头指针

   int rear;       //尾指针

}SqQueue;

程序:

#include<iostream>
using namespace std;
#define MAXQSIZE 100
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int QElemType;
typedef int Status;
typedef struct{
   QElemType *base;
   int front;      //头指针
   int rear;       //尾指针
}SqQueue;
//循环队列的初始化
Status InitQueue(SqQueue &Q)
{
   Q.base = newQElemType[MAXQSIZE];
   if(!Q.base)
   {
       return OVERFLOW;
   }
   Q.front = Q.rear=0;
   return OK;
}
//循环队列的入队
Status EnQueue(SqQueue &Q,QElemType e)
{
   if((Q.rear+1)%MAXQSIZE ==Q.front)
   {
       return ERROR;//队列满
   }
   Q.base[Q.rear] = e;
   Q.rear =(Q.rear+1)%MAXQSIZE;
   return OK;
}
//循环队列的出队
Status DeQueue(SqQueue &Q,QElemType &e)
{
   if(Q.rear == Q.front)
   {
       return ERROR;
   }
   e = Q.base[Q.front];
   Q.front =(Q.front+1)%MAXQSIZE;
   return OK;
}
int main()
{
   SqQueue Q;
   QElemType e;
   cout<<"进循环队列的元素依次为:"<<endl;
   if(InitQueue(Q)==OK)
       for(intj=1;j<=18;j++)
       {
           EnQueue(Q,j);
           cout<<j<<"";
       }
   cout<<endl<<"依次出队的元素为:"<<endl;
   while(Q.rear != Q.front)
   {
       DeQueue(Q,e);
       cout<<e<<"";
   }
   return 0;
}

*5.综合训练:1)利用栈实现表达式求值算法。

  程序:

/***链栈实现表达式求值***/
#include<iostream>
using namespace std;

const char oper[7] = {'+','-','*','/','(',')','#'};
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef char SElemType;
typedef int Status;
typedef struct SNode{
	int data;
	struct SNode *next;
}SNode,*LinkStack;

Status InitStack(LinkStack &S)
{
	S = NULL;
	return OK;
}
bool StackEmpty(LinkStack S)
{
	if(!S)
		return true;
	return false;
}
Status Push(LinkStack &S,SElemType e)
{
	SNode *p = new SNode;
	if(!p)
	{
		return OVERFLOW;
	}
	p->data = e;
	p->next = S;
	S = p;
	return OK;
}
Status Pop(LinkStack &S,SElemType &e)
{
	SNode *p;
	if(!S)
		return ERROR;
	e = S->data;
	p = S;
	S = S->next;
	delete p;
	return OK;
}
Status GetTop(LinkStack &S,SElemType &e)
{
	if(!S)
		return ERROR;
	e = S->data;
	return OK;
}
bool In(char ch)
{//判断ch是否为运算符
	for(int i = 0;i < 7;i ++)
	{
		if(ch == oper[i])
		{
			return true;
		}
	}
	return false;
}
char Precede(char theta1,char theta2)
{//判断运算符优先级
	if((theta1 == '('&&theta2 == ')')||(theta1 == '#'&&theta2 == '#'))
	{
		return '=';
	}
	else if(theta1 == '('||theta1 == '#'||theta2 == '('
		||(theta1 == '+'||theta1 == '-')&&(theta2 == '*'||theta2 == '/'))
	{
		return '<';
	}
	else
		return '>';
}
char Operate(char first,char theta,char second)
{//计算两数运算结果
	switch(theta)
	{
	case '+':
		return (first - '0')+(second - '0')+ 48;
	case '-':
		return (first - '0')-(second - '0')+ 48;
	case '*':
		return (first - '0')*(second - '0')+ 48;
	case '/':
		return (first - '0')/(second - '0')+ 48;
	}
	return 0;
}

//算法3.10 表达式求值
char EvaluateExpression()
{
	// 算术表达式求值的算符优先算法。设OPTR和OPND分别为运算符栈和操作数栈,
	// OP 为运算符集合
	LinkStack OPTR,OPND;
	char ch,theta,a,b,x,top;
	InitStack ( OPTR);
	Push (OPTR,'#');
	InitStack ( OPND);
	ch = getchar();
	while (ch != '#' || (GetTop(OPTR,top) ,top!= '#') )
	{
		if (!In(ch))
		{
			Push(OPND, ch);
			ch = getchar();
		} // ch不是运算符则进栈
		else
			switch (GetTop(OPTR, top),Precede(top,ch))
			{ //比较OPTR的栈顶元素和ch的优先权
			case '<': //当前字符ch压入OPTR栈,读入下一字符ch
				Push(OPTR, ch);
				ch = getchar();
				break;
			case '>': //弹出OPTR栈顶的运算符进行相应运算,并将运算结果入栈
				Pop(OPTR, theta);
				Pop(OPND, b);
				Pop(OPND, a);
				Push(OPND, Operate(a, theta, b));
				break;
			case '=': //脱括号并接收下一字符
				Pop(OPTR, x);
				ch = getchar();
				break;
			} // switch
	} // while
	GetTop(OPND,ch);
	return ch;
} // EvaluateExpression

int main()
{
	cout<<"请输入要计算的表达式(操作数和结果都在0-9的范围内,以#结束):"<<endl;
	char res = EvaluateExpression();
	cout<<"计算结果为"<<res<<endl;
	return 0;
}

四、实验心得体会:(包括遇到的问题及解决办法)

1)从数据结构的定义看,栈和队列也是一种线性表。其与线性表的不同之处在于栈和队列的相关运算具有特殊性,只是线性表相关运算的一个子集。一般线性表的上的插入、删除运算不受限制,而栈和队列上的插入、删除运算受某种特殊限制。因此。栈和队列也称为操作受限的线性表。

2)栈在计算机中的地位很重要,例如表达式求值,函数调用时都需要用到栈的结构。

算术表达式由常量、变量、运算符和括号组成。由于不同的运算符具有不同的优先级,又要考虑括号,因此,算术表达式的求值不可能严格地从左到右进行。因而在程序设计时,借助栈实现。

3)我感觉,最重要的还是把基础掌握,掌握了基础,很多问题就不是问题,只要按部就班就可以了。这次试验,我感觉自己还有很多比较薄弱的地方,我感到自己对于指针的理解还不是很透彻,对于指针的运用也不是十分的熟练,因此,在后的学习中,我会更加重视这方面的学习,力争掌握这门学科。

五、指导教师意见及成绩

 

 

                                                                                                                      签名:

                                                                                                                      年        月      


猜你喜欢

转载自blog.csdn.net/qq_30757161/article/details/80383895