逆波兰中缀转后缀表达式并求值

建立链栈

“Linkstack.h”

#pragma once

typedef int Elemtype;

typedef struct _Node
{
	Elemtype data;
	char ptr;
	struct _Node* next;
	
}Node;

typedef struct _Linkstack
{
	Node head;

}Linkstack,*ptrstack;

//初始化
void init(ptrstack stack);
//入栈1
void Push(ptrstack stack,int val);
//出栈1
void Pop(ptrstack stack,int *val);
//入栈2
void Push1(ptrstack stack,char ptr);
//出栈2
void Pop1(ptrstack stack,char *ptr);
//清空
void clear(ptrstack stack);
//销毁
void destroy(ptrstack stack);
//后缀表达式求值
int RPN_num(ptrstack stack,char *str);
//中缀转后缀
void RPN_change(ptrstack stack,char *str,char *brr);

.cpp

#include"Linkstack.h"
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<assert.h>
#include<malloc.h>
#include<ctype.h>

void init(ptrstack stack)
{
	assert(stack!=NULL);
	if(stack==NULL)
	{
		return;
	}
	stack->head.next=NULL;
}

void Push(ptrstack stack,int val)
{
	assert(stack!=NULL);
	if(stack==NULL)
	{
		return ;
	}

	Node* newnode=(Node*)malloc(sizeof(Node));
	newnode->data=val;
	newnode->next=stack->head.next;
	stack->head.next=newnode;
}

void Pop(ptrstack stack,int *val)
{
	assert(stack!=NULL);
	if(stack==NULL)
	{
		return ;
	}
	if(stack->head.next==NULL)
	{
		return ;
	}

	Node* q=stack->head.next;
	*val=q->data;
	stack->head.next=q->next;
	free(q);
	q=NULL;

}
void Push1(ptrstack stack,char ptr)
{
	assert(stack!=NULL);
	if(stack==NULL)
	{
		return ;
	}

	Node* newnode=(Node*)malloc(sizeof(Node));
	newnode->ptr=ptr;
	newnode->next=stack->head.next;
	stack->head.next=newnode;
}
void Pop1(ptrstack stack,char *ptr)
{
	assert(stack!=NULL);
	if(stack==NULL)
	{
		return ;
	}
	if(stack->head.next==NULL)
	{
		return ;
	}
	Node* q=stack->head.next;
	*ptr=q->ptr;
	stack->head.next=q->next;
	free(q);
	q=NULL;
}
中缀转后缀:

在这里插入图片描述

例如:9 + ( 3 - 1 )* 10+ 10 / 2 —> 9 3 1 - 10 * + 10 2 / +
思想:
1.循环遍历字符串:
(1)遇到数字或者空格就直接输出(这里输出是指将其保存在额外给的数组里)
(2)否则:
遇到加减:如果栈为空就压栈,不为空则判断与栈顶元素的优先级,因为加减小于乘除,而且同级别也需要输出的关系,即只要栈顶元素为加减乘除的任意一个,就循环出栈并输出,直到栈为空。
遇到乘除或者左括号,就直接压栈。
遇到右括号,就将栈中元素依次出栈并输出,直到遇到左括号。同时再将左括号出栈。
2.遍历结束之后,因为栈中可能依然有元素的关系,我们需要依次出栈并输出。

void RPN_change(ptrstack stack,char *str,char *brr)
{
	assert(stack!=NULL&&str!=NULL);
	if(stack==NULL||str==NULL)
	{
		return ;
	}

	int i=0,j=0;
	char p;
	
	while(str[i]!='\0')
	{
		if(isdigit(str[i]))
		{
			brr[j++]=str[i];
			i++;
		}
		else if(str[i]==' ')
		{
			brr[j++]=str[i++];
		}
		else
		{
			if(str[i]=='+'||str[i]=='-')
			{
				Node *q=stack->head.next;
				if(stack->head.next==NULL)
				{
					Push1(stack,str[i]);
				}
				else
				{
					if(q->ptr=='/'||q->ptr=='+'||q->ptr=='-'||q->ptr=='*')
					{
						while(stack->head.next!=NULL)
						{
							Pop1(stack,&brr[j++]);
						}
					}
					Push1(stack,str[i]);	
				}
			}
			else if(str[i]==')')
			{
				while(stack->head.next->ptr!='(')
				{
					Pop1(stack,&brr[j++]);
				}
				Pop1(stack,&p);
			}
			else if(str[i]=='*'||str[i]=='/'||str[i]=='(')
			{
				Push1(stack,str[i]);
			}
			i++;
		}
	}
	while(stack->head.next!=NULL)
	{
		Pop1(stack,&brr[j++]);
	}
	brr[j]='\0';
}
后缀表达式求值:

思想:
1.循环遍历字符串:
(1)遇到数字就直接压栈;因为是字符的关系,为了以免而会将原先一个数字字符分成两个字符,需要用一个标记记录当前这个是数字并保存值,下一次循环再次遇到数字时,就用保存的值*10+当前的数字。
(2)遇到空格就直接输出。
(3)遇到符号就将栈顶的两个元素出栈,第一个作为right,第二个作为left,然后将他们计算得出的值压栈。

int RPN_num(ptrstack stack,char *str)
{
	assert(stack!=NULL&&str!=NULL);
	if(stack==NULL||str==NULL)
	{
		return NULL;
	}
	int num=0;
	int i=0;
	int left,right;
	int flg=-1,count=0;

	while(str[i]!='\0')
	{
		if(isdigit(str[i]))
		{
			if(flg==-1)
			{
				count=(str[i]-'0');
				Push(stack,count);
				flg=1;
				i++;
			}
			else if(flg==1)
			{
				count=count*10+(str[i]-'0');
				Pop(stack,&left);
				Push(stack,count);
				i++;
				flg=1;
			}
		}
		else if(str[i]=='+')
		{
			Pop(stack,&right);
			Pop(stack,&left);
			Push(stack,left+right);
			count=0;
			flg=-1;
			i++;
		}
		else if(str[i]=='-')
		{
			Pop(stack,&right);
			Pop(stack,&left);
			Push(stack,left-right);
			count=0;
			flg=-1;
			i++;
		}
		else if(str[i]=='*')
		{
			Pop(stack,&right);
			Pop(stack,&left);
			Push(stack,left*right);
			count=0;
			flg=-1;
			i++;
		}
		else if(str[i]=='/')
		{
			Pop(stack,&right);
			Pop(stack,&left);
			Push(stack,left/right);
			count=0;
			flg=-1;
			i++;
		}
		else if(str[i]==' ')
		{
			count=0;
			flg=-1;
			i++;
		}
	}
	Pop(stack,&num);
	return num;
}

测试

Linkstack p;
init(&p);

char str[]="9 + ( 3 - 1 ) * 10 + 10 / 2";
char *brr=new char[strlen(str)+1]();
RPN_change(&p,str,brr);
printf("%s\n",brr);
//char str[]="9 3 1- 3 * + 10 2 / +";

int num=RPN_num(&p,brr);
printf("%d\n",num);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值