利用栈和队列数据结构实现中缀转后缀表达式

中缀转后缀

**后缀表达式的运算过程**:遇到数字入栈,遇到运算符从栈中弹出两个元素,结算结果,结果入栈,继续扫描.

**中缀转后缀**:
```
1. 扫描字符串,遇到数字,入队
2. 遇到符号  
    2.1 如果栈为空则入栈
    2.2 符号为左括号则入栈
    2.3 符号为右括号,则依次弹出栈顶符号入队,直到遇到左括号
    2.4 如果栈不为空,则与栈中符号比较优先级
        2.4.1 如果栈顶为小括号,则直接入栈
        2.4.2 如果比栈中的符号优先级高,则符号入栈
        2.4.1 如果比栈中符号优先级低或者相等, 则依次弹出栈中的符号入队,直到遇到小括号或者栈中的符号优先级比它低或者栈为空才会将自身入栈
3. 遇到末尾,则依次弹出栈中符号,并依次入队

代码如下

#define _CRT_SECURE_NO_WARNINGS 
#include "MyList.h"
#include <iostream>
#include <stdlib.h>
using namespace std;
bool Compare(char cSymbol1, char cSymbol2)
{
  switch (cSymbol1)
  {
  case '+':
  case'-':
    return false;
  case '*':
  case '/':
    if ((cSymbol2 == '(') || (cSymbol2 == ')'))
    {
      return false;
    }
    else
    {
      return true;
    }

  }

}
/*
1. 扫描字符串,遇到数字,入队
2. 遇到符号
2.1 如果栈为空则入栈
2.2 符号为左括号则入栈
2.2 符号为右括号,则依次弹出栈顶符号入队,直到遇到左括号
2.3 如果栈不为空,则与栈中符号比较优先级
2.3.1 如果栈顶为小括号,则直接入栈
2.3.2 如果比栈中的符号优先级高,则符号入栈
2.3.1 如果比栈中符号优先级低或者相等,则弹出栈中的符号入队,继续比较(遇到小括号或者比它高或者栈为空才会比较完)
3. 遇到末尾,则依次弹出栈中符号,并依次入队
*/

int main()
{
  CMyList cList;

  char szBuf[100];
  memset(szBuf, 0, 100);
  cout << "请输入你要转换的中缀表达式:" << endl;
  scanf("%s", szBuf);

  char szNumber[10];
  memset(szNumber, 0, 10);

  char* pNum = NULL;
  char* pSymbol = NULL;
  pSymbol = szBuf;
  pNum = szBuf;
  for (pSymbol = szBuf; *pSymbol != '\0'; ++pSymbol)
  {
    if (*pSymbol < '0' || *pSymbol > '9')
    {
      int nLen = pSymbol - pNum;
      if (nLen > 9)
      {
        cout << "输入的数字大于9位数" << endl;
        return -1;
      }

      char szTmpNumBuf[10] = { 0 };
      strncpy(szTmpNumBuf, pNum, nLen);
      char szTmpSymbol[10] = { 0 };
      strncpy(szTmpSymbol, pSymbol, 1);
      pNum = pSymbol + 1;

      //数字入队列
      if (nLen > 0)
      {
        cList.PushBack(szTmpNumBuf);
      }
      //如果栈为空则入栈
      if (cList.IsStatckEmpty())
      {
        cList.PushFront(szTmpSymbol);
        continue;
      }
      //符号为左括号则入栈
      if (szTmpSymbol[0] == '(')
      {
        cList.PushFront(szTmpSymbol);
        continue;
      }
      //符号为右括号,则依次弹出栈顶符号入队,直到遇到左括号
      CMyList::CListNode* pNode;
      if (szTmpSymbol[0] == ')')
      {
        cList.GetTop(&pNode);
        while (pNode->szData[0] != '(')
        {
          cList.PushBack(pNode->szData);//栈顶元素入队列
          cList.PopFrontStatck();//出栈
          cList.GetTop(&pNode);
        }
        cList.PopFrontStatck();//把左括号出栈
        continue;
      }

      cList.GetTop(&pNode);
      while (pNode != nullptr)
      {
        //比较的时候
        //如果栈顶为小括号,则直接入栈
        if (pNode->szData[0] == '(')
        {
          cList.PushFront(szTmpSymbol);
          break;
        }
        //如果比栈中的符号优先级高, 则符号入栈
        if (Compare(szTmpSymbol[0], pNode->szData[0]))
        {
          cList.PushFront(szTmpSymbol);
          break;
        }
        else
        {
          //如果比栈中符号优先级低或者相等, 则依次弹出栈中的符号入队,直到遇到小括号或者栈中的符号优先级比它低或者栈为空才会将自身入栈)
          cList.PushBack(pNode->szData);//栈顶元素入队列
          cList.PopFrontStatck();//出栈
          cList.GetTop(&pNode);
        }
      }
      //比较完后还没有找到优先级高的栈中的符号都入队了,此时栈为空,符号入栈
      if (pNode == nullptr)
      {
        cList.PushFront(szTmpSymbol);
        continue;
      }
    }
  }

  //循环完毕处理最后一个数字并把栈全部放入队列中
  //遇到末尾, 则依次弹出栈中符号, 并依次入队
  int nLen = pSymbol - pNum;
  if (nLen > 9)
  {
    cout << "输入的数字大于9位数" << endl;
    return -1;
  }
  char szTmpNumBuf[10] = { 0 };
  strncpy(szTmpNumBuf, pNum, nLen);
  if (nLen > 0)
  {
    cList.PushBack(szTmpNumBuf);
  }
  CMyList::CListNode* pNode;
  cList.GetTop(&pNode);
  while (pNode != nullptr)
  {
    cList.PushBack(pNode->szData);//栈顶元素入队列
    cList.PopFrontStatck();//出栈
    cList.GetTop(&pNode);
  }
  cout << "转换后的结果:" << endl;
  CMyList::CListNode* pNodeQueue;
  cList.GetQueue(&pNodeQueue);
  while (pNodeQueue != nullptr)
  {
    cout << pNodeQueue->szData;
    cList.PopFrontQueue();
    cList.GetQueue(&pNodeQueue);
  }
  cout << endl;

  /*
  //运算没有写完,遍历队列,数字就放入栈中,符号就运算
  */
  system("pause");
  return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值