06栈的基本运行与表达式求值

:
栈就是操作受限制的线性表,它的删除与插入插做只能在栈顶进行,降低了时间复杂度。在写程序时要注意判断它栈空或栈满的情况,以免出错
代码
1.定义结构体

typedef struct CharStack {
    int top;

    int data[STACK_MAX_SIZE]; //The maximum length is fixed.
} *CharStackPtr;

2.栈的初始化

//栈的初始化
int InitiaStark(SqStark S)
{
 
	S->base=(int*)malloc(sizeof(int)*Maxsize);
	if(!S->base)
	{
		return 0;
	}
	
		S->top=S->base;
		S->stacksize=Maxsize;
	
	return 1;
}

3.判断是否为空

//判断栈是否为空
int Stackempty(SqStark S)
{
	if(S->top==S->base)
	return 1;//空栈 
	else
	return 0;
 } 

4.求元素个数


int Starkelemlength(SqStark S)
{
	if(S->base=S->top)
	return 0;
	else
	return (int)(S->top-S->base);
}

5.顺序栈的入栈与出栈

//顺序栈的入栈
SqStark pushelem(SqStark S,int e)
{
	if(S->top-S->base>=S->stacksize)//判断是否栈满 
	return;
	*S->top=e;
	S->top++;
	return S;
 } 
 //顺序栈的出栈
SqStark popelem(SqStark S)
{
	if(S->top==S->base)
	return;//判断栈是否为空,若为空则不能在出栈
	int elem;
	S->top--;
	*S->top=elem;
	return S; 
 } 
#include <stdio.h>
#include <stdlib.h>
#define Maxsize 5
 
typedef struct{
	int *top;//栈顶指针 
	int *base;//栈底指针 
	int stacksize;//表示栈可使用的最大容量 
}*SqStark; 
 
//栈的初始化
int InitiaStark(SqStark S)
{
 
	S->base=(int*)malloc(sizeof(int)*Maxsize);
	if(!S->base)
	{
		return 0;
	}
	
		S->top=S->base;
		S->stacksize=Maxsize;
	
	return 1;
}
 
//判断栈是否为空
int Stackempty(SqStark S)
{
	if(S->top==S->base)
	return 1;//空栈 
	else
	return 0;
 } 
 
//判断栈中元素个数
int Starkelemlength(SqStark S)
{
	int length=0;
	while(S->base!=S->top)
	{
		length++;
		S->base++;
	}
 
}
int Starkelemlength(SqStark S)
{
	if(S->base=S->top)
	return 0;
	else
	return (int)(S->top-S->base);
}
 
//清空顺序栈
int ClearStark(SqStark S)
{
	if(S->base)
	S->top=S->base;//这步很重要 
	return 1;
 } 
 
 //销毁顺序栈
int DestroyStark(SqStark S)
{
	if(S->base)
	{
		free(S->base);
		S->stacksize=0;
		S->top=S->base=NULL;
	}
	return 1;
 } 
 
 //顺序栈的入栈
SqStark pushelem(SqStark S,int e)
{
	if(S->top-S->base>=S->stacksize)//判断是否栈满 
	return;
	*S->top=e;
	S->top++;
	return S;
 } 
 //顺序栈的出栈
SqStark popelem(SqStark S)
{
	if(S->top==S->base)
	return;//判断栈是否为空,若为空则不能在出栈
	int elem;
	S->top--;
	*S->top=elem;
	return S; 
 } 
 
void printStark(SqStark S)
{
	int elem;
     while(S->base<S->top)
     {
     	elem=*S->base;
     	printf("%5d",elem);
     	S->base++;
	 }
	 printf("\n");
}
 
int main()
 {
 	SqStark S;
 	int result;
 	result=InitiaStark(S);
 	if(result==1)
 	printf("Success initia\n");
 	int i;
 	int elem;//要入栈的元素 
 	printf("please print the elems you want to push\n");
 	for(i=0;i<Maxsize;i++)
	 {
	 	scanf("%d",&elem);
	 	pushelem(S,elem);
	 }
	 printf("Success in pushing elems\n");
	 printf("The new stark is:\n");
	 printStark(S);
	 int result_1;
	 result_1=Stackempty(S);
	 if(result_1==1)
	 printf("The stark is empty\n");
 	 else
 	 printf("The stack is not empty\n");
 	 int result_2;
 	 result_2=Starkelemlength(S);
 	 printf("The elems in the stark is %d",result_2);
 	 S=popelem(S);
 	 printStark(S);
 	 int result_3;
 	 result_3= ClearStark(S);
 	 if(result_3==1)
 	 printf("Success clear\n");
 	 int result_4=DestroyStark(S);
 	 if(result_4==1)
     printf("Success destroy\n");
     return 0;
 }
 ```c
 ---- pushPopTest begins. ----
After initialization, the stack is:
Pushing a.
a
Pushing b.
a b
Pushing c.
a b c
Pushing d.
a b c d
Pushing e.
a b c d e
Pushing f.
a b c d e f
Pushing g.
a b c d e f g
Pushing h.
a b c d e f g h
Pushing i.
a b c d e f g h i
Pushing j.
a b c d e f g h i j
Pushing k.
Cannot push element: stack full.
a b c d e f g h i j
Pushing l.
Cannot push element: stack full.
a b c d e f g h i j
Pop j.
a b c d e f g h i
Pop i.
a b c d e f g h
Pop h.
a b c d e f g
---- pushPopTest ends. ----
Press any key to continue

二 表达式求值

表达式求值:在看了许多份不同的版本后,我有些理解了然后下列是我临摹别人的代码。但是这个代码的确缺点是没有中括号的包含。

/*
   栈的应用----表达式求值。 
*/
#include <stdio.h>		// 引用输入(scanf)、输出(printf)函数的头文件; 
#include <stdlib.h>		// 引用 malloc free 函数的头文件; 

//构建栈的结构 
typedef struct LinkNode{
   char str;
   LinkNode *next;
}LinkNode, *LinkStack; 

//栈的初始化 
void InitStack(LinkStack &S)
{
   S = NULL;
}

//栈空的判断 
bool EmptyStack(LinkStack S)
{
   if (S == NULL)
   	return true;
   else
   	return false;
}

//进栈操作;单链表的前插操作 
void InsertStack(LinkStack &S, char str)
{
   LinkNode *p;		//定义一个指针结点; 
   p = (LinkNode *)malloc(sizeof(LinkNode));	//分配空间; 
   p->str = str;		//赋值该节点的str属性值; 
   p->next = S;		
   S = p;				//修改 S 的指向 
}

//出栈操作 
bool DeleteStack(LinkStack &S, char &str)
{
   if (EmptyStack(S))	//栈空报错; 
   	return false;
   LinkNode *p = S;	//定义一个指针结点,使其指向要被删除的栈顶结点; 
   str = p->str;		//用str记录要被弹出栈的元素值,并传递出去; 
   S = p->next;		//修改S指针指向的位置; 
   free(p);			//释放要被删除的结点 
   return true;
}

//获取栈顶元素,用str传递栈顶元素; 
bool GetStack(LinkStack S, char &str) 
{
   if (EmptyStack(S))	//栈空报错; 
   	return false;
   str = S->str;
   return true;
}

//进行 + - * / 运算,将计算结果用Lnum传递; 
bool Operation(char &Lnum, char Rnum, char operation) 
{
   switch (operation)
   {
   	case '+':
   		Lnum = Lnum + Rnum;
   		break;
   	case '-':
   		Lnum = Lnum - Rnum;
   		break;
   	case '*':
   		Lnum = Lnum * Rnum;
   		break;
   	case '/':
   		if (Rnum == 0)
   		{
   			printf("除数不能为0!\n");
   			return false;
   		}
   		Lnum = Lnum / Rnum;
   		break;
   	default:
   		printf("有不合法的运算符!\n");
   		return false; 
   		break;
   }
   return true;
} 

//比较运算符的顺序;用result传递比较结果; 
bool Compare(char one, char topchar, char &result) 
{
   switch (one)
   {
   	case '+':
   	case '-':
   		if (topchar == '(')
   			result = '<';	//'+' '-' 进栈; 
   		else
   			result = '>';	
   		break;
   	case '*':
   	case '/':
   		if (topchar == '*' or topchar == '/')
   			result = '>';
   		else
   			result = '<';	//'*' '/' 进栈; 
   		break;
   	case '(':
   		result = '<';
   		break;
   	case ')':
   		result = '=';
   		break;
   	default :
   		printf("有不合法的运算符!\n"); 
   		return false;
   		break;
   }
   return true;
}

int main() 
{
   LinkStack Snum, Schar;
   InitStack(Snum);		//初始化操作数栈; 
   InitStack(Schar);		//初始化运算符栈; 
   printf("Function:\n"); 
   printf("栈的应用-----表达式求值\n");
   printf("input what you want to calculator:");
   char *op = (char *)malloc(sizeof(char));	//为指针op分配空间; 
   gets(op);			//赋值;
   char topstr,result;		//记录栈顶符号和比较之后的结果; 
   char Lnum,Rnum;			//记录左,右操作数; 
   while (*op)				//循环指针op,直到找到结束符'\0'结束; 
   {
   	//如果此时是操作数,循环判断下一位是否是数字; 
   	if (*op >= '0' and *op <= '9')
   	{
   		char num = 0; 
   		//eg:读入数据是19,则从左到右读取:1*10+9; 
   		while (*op >= '0' and *op <= '9')
   		{
   			num = *op - '0' + num * 10;
   			*op++;
   		}
   		InsertStack(Snum,num);		//将操作数入栈; 
   		*op--;						//恢复上一个指针指向; 
   	}else if (*op == '+' or *op == '-' or *op == '*' or *op == '/' or *op == '(' or *op == ')') 
   	{
   		//比较操作大小,再考虑是否入栈或者进行计算;
   		if (!EmptyStack(Schar))				//栈不为空; 
   		{	
   			GetStack(Schar, topstr);		//获取栈顶操作符; 
   			Compare(*op, topstr, result);
   			switch (result) 
   			{
   				case '>':
   					//弹出栈顶操作符,进行运算;
   					DeleteStack(Schar,topstr);
   					if (!DeleteStack(Snum,Rnum))
   					{
   						printf("右操作数匹配失败。\n");
   						return 1;
   					}
   					if (!DeleteStack(Snum,Lnum))
   					{
   						printf("左操作数匹配失败。\n");
   						return 1;
   					}						
   					if (!Operation(Lnum,Rnum,topstr))
   						return 1;
   					InsertStack(Snum,Lnum);		//将计算后的结果重新放入操作数栈;	
   					InsertStack(Schar,*op);		//将操作符放入操作符栈; 
   					break;
   				case '<':
   					InsertStack(Schar, *op);	//将操作符入栈;
   					break;
   				case '=':
   					//弹出栈顶操作符,进行运算,直到找到‘(’;
   					GetStack(Schar,topstr);		//读取栈顶操作符; 
   					while(topstr != '(') 
   					{
   						DeleteStack(Schar,topstr);
   						if (!DeleteStack(Snum,Rnum))
   						{
   							printf("右操作数匹配失败。\n");
   							return 1;
   						}
   						if (!DeleteStack(Snum,Lnum))
   						{
   							printf("左操作数匹配失败。\n");
   							return 1;
   						}						
   						if (!Operation(Lnum,Rnum,topstr))
   							return 1;
   						InsertStack(Snum,Lnum);		//将计算后的结果重新放入操作数栈;							
   						GetStack(Schar,topstr);		//读取栈顶操作符;
   					}
   					DeleteStack(Schar,topstr);
   					break;
   			}
   		}else{
   			//栈空操作符直接进栈; 
   			InsertStack(Schar, *op);	//将操作符入栈;
   		} 		
   	}else if(*op != ' ')				//完善程序的健壮性,不是空格符报错; 
   	{
   		printf("发现不法符号!退出程序。\n");
   		return 1; 
   	}	 
   	*op++;
   }
   while(!EmptyStack(Schar)) 
   {
   	//弹出栈顶操作符,进行运算;
   	DeleteStack(Schar,topstr);
   	if (!DeleteStack(Snum,Rnum))
   	{
   		printf("右操作数匹配失败。\n");
   		return 1;
   	}
   	if (!DeleteStack(Snum,Lnum))
   	{
   		printf("左操作数匹配失败。\n");
   		return 1;
   	}						
   	if (!Operation(Lnum,Rnum,topstr))
   		return 1;
   	InsertStack(Snum,Lnum);		//将计算后的结果重新放入操作数栈;
   }
   DeleteStack(Snum,topstr);
   printf("%d",topstr);	
   return 0;
}

请添加图片描述

体验:初始化一个栈,用于保存暂时还不能确定运算顺序的运算符。从左到右处理各个元素,直到末尾。可能遇到以下三种情况:

遇到操作数,直接加入后缀表达式。
遇到界限符,遇到“(”直接入栈,遇到“)”则依次弹出栈内运算符并加入后缀表达式,直到弹出“(”为止。注意:“(” 不加入后缀表达式。
遇到运算符。依次弹出栈中优先级高于或等于当前运算符的所有运算符,并加入后缀表达式,若碰到“(”或栈空则停止,之后再把当前运算符入栈。
按上述方法处理完所有字符后,将栈中剩余运算符依次弹出,并加入后缀表达式。用栈实现中缀表达式的计算:

初始化两个栈,操作数栈和运算符栈;
若扫描到操作数,压入操作数栈;
若扫描到运算符或界限符,则按照“中缀转后缀”相同的逻辑压入运算符栈(期间也会弹出运算符,每当弹出一个运算符时,就需要再弹出两个操作数栈的栈顶元素并执行相应运算,运算结果再压回操作数栈;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值