双端队列栈的应用 逆波兰表达式求值

1.目的

基于双端队列的头插、头删操作,完成栈的应用:逆波兰表达式求值,测试和调试程序。
遇到操作数,则入栈;
遇到二元运算符,则连续从栈中弹出两个操作数,先弹出的做第二操作数,后弹出的做
第一操作数,与该二元运算符作用后,将得到的结果再存入栈中;
遇到一元运算符,则从栈中弹出一个操作数,与该一元运算符作用后,将得到的结果再
存入栈中;
按照上面的规则,扫描后缀表达式(由键盘读到):2、3 是操作数,依次入栈;之后
碰到加号“+”这个二元运算符,则 3、2 依次出栈,2 为第一操作数,3 为第二操作数,
执行加法,和为 5,入栈;加号后面的 6 是操作数入栈;之后的乘号“*”是二元运算
符,则 6、5 依次出栈,5 为第一操作数,6 为第二操作数,执行乘法,积为 30,入
栈;之后可以使用打印栈顶元素的操作(该次实验中使用命令“p”),将最后结果在
屏幕上输出。
程序要求从键盘接收字符串,然后按照上面的思想,求解该字符串对应的逆波兰式表达
式的值。

2.程序
头文件引用dlist.cpp(见上条博客 :用C++语言实现双端队列)

#include<iostream>
#include"dlist.cpp"

using namespace std;

bool do_command(Dlist<int> &mylist,char *n)  //根据输入字符执行相应操作
{
    int *p = NULL;
    int *q = NULL;
    Dlist<int> temp;
    switch (*n) {
    case '+': //'+'表示取出栈顶两个数据相加
        p = mylist.removeFront(); //取出原表中的第一个元素
        q = mylist.removeFront(); //取出原表中的第二个元素
        if(NULL != q) //判断表中的数据是否够两个
        {
            *q = *p + *q; //将两个数相加
            mylist.insertFront(q); //将结果插入表中
        }
        else{ //如果第二个指针是空,则原表中说明不够两个元素
            if(p != NULL) mylist.insertFront(p); //如果第一个元素被取出,则重新插回
            cout << "Not enough operands\n"; //输出信息
        }
        return true;
    case '-': //'-'表示取出栈顶两个数据相减
        p = mylist.removeFront();//取出原表中的第一个元素
        q = mylist.removeFront();//取出原表中的第二个元素
        if(NULL != q) //判断表中的数据是否够两个
        {
            *q = *q - *p; //将两个数相减
            mylist.insertFront(q);//将结果插入表中
        }
        else{//如果第二个指针是空,则原表中说明不够两个元素
            if(p != NULL) mylist.insertFront(p); //如果第一个元素被取出,则重新插回
            cout << "Not enough operands\n"; //输出信息
        }
        return true;
    case '*': //'*'表示取出栈顶两个数据相乘
        p = mylist.removeFront();
        q = mylist.removeFront();
        if(NULL != q)
        {
            *q = *q * *p;//将两个数相乘
            mylist.insertFront(q);
        }
        else{
            if(p != NULL) mylist.insertFront(p);
            cout << "Not enough operands\n";
        }
        return true;
    case '/': //'/'表示取出栈顶两个数据相除
        p = mylist.removeFront();
        q = mylist.removeFront();
        if(NULL != q)
        {
            if(0 == *p) //判断除数是否为0
            {
                cout << "Divide by zero\n";
                return true;
            }
            *q = *q / *p; //将两个数相除
            mylist.insertFront(q);
        }
        else{
            if(p != NULL) mylist.insertFront(p);
            cout << "Not enough operands\n";
        }
        return true;
    case 'n'://'n'表示返回表头元素的相反数
        p = mylist.removeFront(); //取出表头元素
        if(NULL != p)
        {
            *p = *p * (-1); //取相反数
            mylist.insertFront(p); //将结果插回表中
        }
        else{//如果指针是空,则原表中没有元素
            cout << "Not enough operands\n";
        }
        return true;
    case 'd': //'d'复制栈顶元素
        p = mylist.removeFront();//取出表头元素
        if(NULL != p)
        {
            mylist.insertFront(p); //将这个元素插回
            mylist.insertFront(p); //将这个元素插回
        }
        else{//如果指针是空,则原表中没有元素
            cout << "Not enough operands\n";
        }
        return true;
    case 'r': //'r'交换前两个元素的顺序
        p = mylist.removeFront(); //取出原表中的第一个元素
        q = mylist.removeFront(); //取出原表中的第二个元素
        if(NULL != q)
        {
            mylist.insertFront(p); //先插入原来的第二个元素
            mylist.insertFront(q); //再插入第一个元素
        }
        else{ //如果指针是空,则原表中没有元素
            cout << "Not enough operands\n";
        }
        return true;
    case 'p': //'p'打印出表头元素
        p = mylist.removeFront(); //取出原表中的第一个元素
        cout << *p << endl;
        if(NULL != p)
        {
            mylist.insertFront(p); //将表头插回
        }
        else{ //如果指针是空,则原表中没有元素
            cout << "Not enough operands\n";
        }
        return true;
    case 'a': //'a'打印出表中所有元素,原表数据不变
        temp = mylist; //先将表中元素赋给临时表
        p = temp.removeFront();
        while(NULL != p) //遍历,逐个打印临时表中的元素
        {
            cout << *p;
            p = temp.removeFront();
        }
        cout << endl;
        return true;
    case 'c': //'c'清空表中所有元素
        p = mylist.removeFront();
        if(NULL != p) //遍历,逐个删除
        {
            p = mylist.removeFront();
        }
        return true;
    case 'q': //'q'表示结束程序
        return false; //返回false,表示程序结束
    default:
        cout << "Bad input" << endl; //如果没有该指令则返回相应信息
        return true;
    }
}

int main()
{
    Dlist<int> mylist;
    int *nu = NULL;
    char *c = new char();
    char number = 0;
    bool t;

    while(cin >> number)
    {
        if((number >= '0') && (number <= '9')) //检测输入的是不是数字
        {
            nu = new int(number - '0'); //如果是数字就将它赋给指针nu
            mylist.insertFront(nu); //将nu插入表中
        }
        else{ //如果输入的不是数字
            *c = number; //将字符赋给指针c
            t  = do_command(mylist,c); //调用运算函数
            if(!t) //检测程序是否结束
            {
                break; //如果程序结束就退出
            }
        }
    }
    delete nu;
    delete c;
}

3.结果
在这里插入图片描述
结果解释:

 这个程序是双端队列中栈的应用,开始执行的是(3+4)*2这个式子,结果是14存入
 表中,’p’打印出表头元素14,正确。再执行‘+’,此时表中只有一个数,所以应返回
 操作数不够的信息,正确。然后执行‘d’操作,将表头元素赋值,再执行‘+’,此时结
 果应为28,打印表头元素为28,正确,最后-2,结果应为26,打印表头元素为26,
 正确。最后‘q’操作退出程序,程序执行完毕。
/* * 基于双向链表实现双端队列结构 */ package dsa; public class Deque_DLNode implements Deque { protected DLNode header;//指向头节点(哨兵) protected DLNode trailer;//指向尾节点(哨兵) protected int size;//队列中元素的数目 //构造函数 public Deque_DLNode() { header = new DLNode(); trailer = new DLNode(); header.setNext(trailer); trailer.setPrev(header); size = 0; } //返回队列中元素数目 public int getSize() { return size; } //判断队列是否为空 public boolean isEmpty() { return (0 == size) ? true : false; } //取首元素(但不删除) public Object first() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); return header.getNext().getElem(); } //取末元素(但不删除) public Object last() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); return trailer.getPrev().getElem(); } //在队列前端插入新节点 public void insertFirst(Object obj) { DLNode second = header.getNext(); DLNode first = new DLNode(obj, header, second); second.setPrev(first); header.setNext(first); size++; } //在队列后端插入新节点 public void insertLast(Object obj) { DLNode second = trailer.getPrev(); DLNode first = new DLNode(obj, second, trailer); second.setNext(first); trailer.setPrev(first); size++; } //删除首节点 public Object removeFirst() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); DLNode first = header.getNext(); DLNode second = first.getNext(); Object obj = first.getElem(); header.setNext(second); second.setPrev(header); size--; return(obj); } //删除末节点 public Object removeLast() throws ExceptionQueueEmpty { if (isEmpty()) throw new ExceptionQueueEmpty("意外:双端队列为空"); DLNode first = trailer.getPrev(); DLNode second = first.getPrev(); Object obj = first.getElem(); trailer.setPrev(second); second.setNext(trailer); size--; return(obj); } //遍历 public void Traversal() { DLNode p = header.getNext(); while (p != trailer) { System.out.print(p.getElem()+" "); p = p.getNex
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

格格不入ち

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值