栈和队列

栈和队列

四、存储结构说明和定义:

StackInt用来存放操作数和运算结果 StackChar用来存放运算符
typedef struct {//存数字 
	ElemInt *base;
	ElemInt *top;
	int stacksize; 
}StackInt;

typedef struct{//存符号 
	ElemChar *base;
	ElemChar *top;
	int stacksize;
}StackChar;

五、主要算法:

  1. 给出程序的概要设计或主要算法的程序流程图
    采用算符优先法,使用两个工作栈,一个是OPTR 用来寄存运算符,另外一个OPND用来寄存操作数或者是运算结果;
    算法的基本思想是首先将操作数栈为空栈,表达式的起始符‘=’为运算符栈得到底栈元素,用字符数组存放输入的表达式,依次判断字符,如果字符是运算符则进入OPTR栈,如果是操作数则进入OPND栈,直到结束。其中对运算数的操作是利用数组Num存放,再将其转换为数型。

Precede()函数根据下表的算符之间的优先关系进行了比较,判断了算符的优先。

  1. 给出核心函数的算法(用类C语言,请注意算法与源程序书写方式的区别)
int EvaluateExpression(StackInt OPND,StackChar OPTR)//算符优先法 :OPTR 运算符栈 OPND运算数栈 
{
	InitChar(OPTR); 
	PushChar(OPTR,'=');// 
	InitInt(OPND);  
	//数字的处理   
	gets(SS); //输入表达式 
	p=SS;
	while(*p!='='||GetTopChar(OPTR)!='=')
	{
		if(!In(*p)){//不是符号 是数字 
			Num[i]=*p;
			i++;
			p++; 
			if(In(*p))
			{
				Num[i]='\0';
				Data=atof(Num);
				PushInt(OPND,Data);
				i=0;
			}
		}
		else //是符号 
			switch(Precede(GetTopChar(OPTR),*p))//判断符号的优先性 
			{
				case '<':	PushChar(OPTR,*p);p++;break;
				case '=':	PopChar(OPTR,x);p++;break;//  )
				case '>':	PopChar(OPTR,theta);   //栈顶元素和当前元素 
							PopInt(OPND,b);
							PopInt(OPND,a);
							PushInt(OPND,Operate(a,theta,b)); //计算结果入栈 
							break;
			}
	}	
	return GetTopInt(OPND);
 }

ElemChar Precede(ElemChar a, ElemChar b)	
{												
	switch(a)
	{
		case '+':if(b == '+' || b == '-' || b == ')' || b == '=') return ('>');
				 else return ('<'); break;
		case '-':if(b == '+' || b == '-' || b == ')' || b == '=') return ('>');
				 else return ('<'); break;
		case '*':if(b == '(') return ('<');
				 else return ('>'); break;
		case '/':if(b == '(') return ('<');
				 else return ('>'); break;
		case '(':if(b == ')') return ('=');
				 else return ('<'); break;
		case ')':return ('>'); break;
		case '=':if(b == '=') return ('=');
			     else return ('<'); break;
	}
}
  1. 给出每个子函数的函数头
    1、ElemInt EvaluateExpression()算符优先法 :OPTR 运算符栈 OPND运算数栈
    2、ElemChar GetTopChar(StackChar S) //返回运算符栈的栈顶元素
    3、ElemInt GetTopInt(StackInt S) //返回运算数栈的栈顶元素
    4、Status In(char c)判断是否为运算符,是运算符则返回 TRUE, 否则返回 FALSE
    5、Status InitChar(StackChar &S) //运算符栈的初始化操作
    6、Status InitInt(StackInt &S) //运算数栈的初始化操作
    7、double Operate(ElemInt a, ElemChar theta, ElemInt b) a,b为运算数theta 为运算符,进行a theta b的四种运算
    8、Status PopChar(StackChar &S, ElemChar &e) //运算符栈的出栈操作
    9、Status PopInt(StackInt &S, ElemInt &e) //运算数栈的出栈操作
    10、ElemChar Precede(ElemChar a, ElemChar b) 判断a b两个运算符的优先级别,a级别高返会> ,b的优先级高返回<,两者相等返回=;
    11、Status PushChar(StackChar &S, ElemChar e) //运算符栈的进栈操作
    12、Status PushInt(StackInt &S, ElemInt e) //运算数栈的进栈操作
    六、程序运行结果测试:
    1、错误的示例。

2、计算:8+9-(6+2)*2=
预测的结果:1
栈的展示:

3、计算:(12+8-9)6+(8-(2+1)(6+1))=
预测的结果:53

七、本次实验小结:

  1. 分析自己的主要算法
    ElemInt EvaluateExpression()算符优先法,对字符只进行一次访问,时间复杂度是O(n);巧妙的利用了数栈和符号栈,进行了表达式的运算。
  2. 说明本次实验中遇到的问题和你的解决方案
    (1)、在实验过程中,我选择了两个栈分别是用来存整型和字符型的数据,但是在输入表达式的过程中采用getchar(),函数getchar()读取stdin流中的下一个字符,因此的入读的是char型数据,导致结果一直是错误的。
    解决方案:使用gets()函数进行输入表达式,简单的讲输入一次进行完成,只需要判断输入的字符串中的字符,只需要对字符进行操作。
  3. 对本次实验的完成情况自我评价
    本次实验的算法按照《[数据结构(C语言版)].严蔚敏_吴伟民》

选题2:迷宫

四、存储结构说明和定义:

typedef struct        
{
    int m, n; //行号列号
    int arr[Size][Size];
}MazeType;

typedef struct
{
    int row; //迷宫中的行
    int col; //迷宫中的列
}PosType;
typedef struct
{
    int step;  //当前位置在路径上的"序号"
    PosType seat;//当前的坐标位置
    DirectiveType di;//往下一个坐标位置的方向
}SElemType; //栈的元素类型
typedef struct
{
    SElemType *base; 
    SElemType *top; 
    int stacksize; 
}SqStack;

五、主要算法:
4. 给出程序的概要设计或主要算法的程序流程图
程序的主要流程图:
在这里插入图片描述

MazePath算法的主要流程图:MazePath(迷宫,起点,终点)
在这里插入图片描述

  1. 给出核心函数的算法(用类C语言,请注意算法与源程序书写方式的区别)
Status  MazePath(MazeType& maze, PosType start, PosType end)
{
    InitStack(s);
    PosType curpos = start;
    int curstep = 1; //探索第一步 
    do {
        if (Pass(maze, curpos))
        {    //没有被访问过 
            FootPrint(maze, curpos);//标为 2 
            e = CreateSElem(curstep, curpos, 1);//创建元素
            Push(s, e);//加入路径
            if (PosEnd(curpos, end))//到达终点
                return true;
            curpos = NextPos(curpos, 1);//获得下一节点
            curstep++;  //探索下一步
        }
        else
        { //当前位置不能通过
            if (!StackEmpty(s))
            {
                Pop(s, e);
                while (e.di==4&&!StackEmpty(s)) //四个方向都访问过了 
                {
                    MarkPrint(maze, e.seat);//标记3 
                    Pop(s, e); //退回一步
                }
                if (e.di < 4)
                {
                    e.di++; //换一个方向探索
                    Push(s, e);
                    curpos = NextPos(e.seat, e.di); 
                }
            }
        }
    } while (!StackEmpty(s));
    return false;
}
  1. 给出每个子函数的函数头
    1、SElemType CreateSElem(int step, PosType pos, int di)创建下一个步的元素,step表示步数,pos是位置,di是方向;
    2、Status DestoryStack(SqStack& s) //销毁栈
    3、bool FootPrint(MazeType& maze, PosType curpos) //访问过的路需要修改标记,这个路径可以通过,标记为2
    4、bool MarkPrint(MazeType& maze, PosType curpos) // 访问过的路 ,不能走的通,标记为3
    5、Status GetTop(SqStack s, SElemType& e)获得栈顶元素
    6、bool InitMaze(MazeType& maze, int a[ROW][COL], int row, int col)//初始化迷宫;
    7、bool Pass(MazeType maze, PosType curpos)//判断这个点是否被访问过
    8、Status InitStack(SqStack& s)初始化栈
    9、Status MazePath(MazeType& maze, PosType start, PosType end)//查找迷宫,maze是迷宫,start是迷宫的起点,end是迷宫的终点(出口)
    10、PosType NextPos(PosType curpos, DirectiveType di) curpos是当前位置,di是下一步的方向,修改下一步的位置;
    11、bool Pop(SqStack& s, SElemType& e)出栈
    12、bool PosEnd(PosType pos1, PosType pos2)判断pos1的位置和pos2的位置是否相同,即判断是否是终点
    13、void PrintMaze(MazeType maze, int row, int col)//打印迷宫
    14、Status Push(SqStack& s, SElemType e)入栈
    15、bool StackEmpty(SqStack s)判断栈是否为空
    六、程序运行结果测试:
    1、输入:
    1 1 1 1 1 1 1 1 1 1
    1 0 1 1 0 0 0 1 0 1
    1 0 0 1 0 0 0 1 0 1
    1 0 1 0 0 1 1 0 0 1
    1 0 1 0 1 0 0 1 0 1
    1 0 0 0 1 0 0 0 1 1
    1 0 0 0 0 0 1 0 1 1
    1 0 1 1 1 0 1 0 0 1
    1 1 0 0 0 1 0 0 0 1
    1 1 1 1 1 1 1 1 1 1
    1 1 8 8

2
输入:
1 1 1 1 1 1 1 1 1 1
1 0 0 1 0 0 0 1 0 1
1 0 0 1 0 0 0 1 0 1
1 0 0 0 0 1 1 0 0 1
1 0 1 0 1 0 0 1 0 1
1 0 0 0 1 0 0 0 0 1
1 0 1 0 0 0 1 0 1 1
1 0 1 1 1 0 1 0 0 1
1 1 0 0 0 1 0 0 0 1
1 1 1 1 1 1 1 1 1 1
1 1 8 2

3、输入
1 1 1 1 1 1 1 1 1 1
1 0 0 1 0 0 0 1 0 1
1 0 0 1 0 0 0 1 0 1
1 0 0 0 0 1 1 0 0 1
1 0 1 1 1 0 0 0 0 1
1 0 0 0 1 0 0 0 0 1
1 0 1 0 0 0 1 0 0 1
1 0 1 1 1 0 1 1 0 1
1 1 0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1
1 1 8 8

九、本次实验小结:
(此栏不允许空白)
4. 分析自己的主要算法
本次实验主要是利用栈先进后出的特点,利用穷举法进行迷宫的求解。其中的主要算法是MazePath();时间复杂度:O(n^2);本次实验用二维数组存放迷宫,用栈存放走过的路径。
5. 说明本次实验中遇到的问题和你的解决方案
1、由于输出函数的打印方式的空格的问题,使迷宫的的呈现误导实验;
2、创建下一个节点时没有返回节点;
解决方案:细化迷宫的打印方式,0,1,2,3用不同的方式;
6. 对本次实验的完成情况自我评价
本次实验利用穷举法进行迷宫问题的求解,很好的利用了栈的先进后出的特点,查找迷宫的出口,用不同的数字标记迷宫访问的路径,清晰的展示了迷宫的访问路径。
缺点:采用穷举法,时间复杂度比较大。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值