栈的顺序存储结构——双栈

本文详细介绍了双栈的顺序存储结构实现,包括构造函数、析构函数、入栈、出栈、获取栈顶元素及判断栈是否为空的操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

栈的顺序存储结构——双栈。

 

双栈的图片:

 

BothStack.h

const int StackSize=100;  //100只是示例数据,需根据具体问题定义
template <class T>
class BothStack 
{
public:
    BothStack( ) {top1= -1;  top2=StackSize;}  //构造函数,将两个栈分别初始化
    ~BothStack( ) { }      //析构函数
    void Push(int i, T x);   //将元素x压入栈i
    T Pop(int i);          //对栈i执行出栈操作
    T GetTop(int i);       //取栈i的栈顶元素
    bool Empty(int i);     //判断栈i是否为空栈
private:
    T data[StackSize];     //存放两个栈的数组
    int top1, top2;        //两个栈的栈顶指针,分别指向各自的栈顶元素在数组中的下标
};

#endif

 

 

BothStack.cpp

//BothStack.cpp
#include "BothStack.h"

/*
 * 前置条件:栈不存在
 * 输    入:无
 * 功    能:栈的初始化
 * 输    出:无
 * 后置条件:构造一个空栈
 */

template <class T>
BothStack<T>::BothStack( )
{
	top1= -1;  
	top2=StackSize;
} 

/*
 * 前置条件:共享空间已存在
 * 输    入:无
 * 功    能:销毁两栈共享的数组空间
 * 输    出:无
 * 后置条件:将两栈共享的数组空间释放
 */

template <class T>
BothStack<T>::~BothStack( ) 
{

}

/* 
 * 前置条件:共享空间已存在
 * 输    入:栈号i,元素值x
 * 功    能:在栈i顶插入一个元素x
 * 输    出:若插入不成功,则抛出插入异常
 * 后置条件:若插入成功,则栈i顶插入了一个栈顶元素
 */

template <class T> 
void BothStack<T>::Push(int i, T x )
{
    if (top1==top2-1) 
		throw "上溢";
    if (i==1) 
		data[++top1]=x;
    if (i==2) 
		data[--top2]=x;
}

/*
 * 前置条件:共享空间已存在
 * 输    入:栈号i
 * 功    能:在栈i中删除栈顶元素
 * 输    出:若删除不成功,则抛出删除异常
 * 后置条件:若删除成功,则栈i中删除了栈顶元素
 */

template <class T>
T BothStack<T>::Pop(int i)
{
    if (i==1) //将栈1的栈顶元素出栈
	{   
        if (top1== -1) 
			throw "下溢";
        return data[top1--];
	}
    if (i==2)  //将栈2的栈顶元素出栈
	{                           
        if (top2==StackSize) 
			throw "下溢";
        return data[top2++]; 
	}
}

/*
 * 前置条件:共享空间已存在
 * 输    入:栈号i
 * 功    能:读取栈i当前的栈顶元素
 * 输    出:若栈i不空,返回栈i当前的栈顶元素值
 * 后置条件:两栈均不变
 */

template <class T> 
T BothStack<T>::GetTop(int i)
{
    if(i==1)
	{
        if (top1!=-1) 
			return data[top1];
	}
    if(i==2)
	{
	    if(top2!=StackSize)
			return data[top2];
   } 
}

/*
 * 前置条件:共享空间已存在
 * 输    入:栈号i
 * 功    能:判断栈i是否为空栈
 * 输    出:若栈i为空栈,返回1;否则返回0
 * 后置条件:两栈均不变
 */

template <class T> 
bool BothStack<T>::Empty(int i)
{  
    if(i==1)
	{
	    if(top1==-1) 
			return 0;
	    else 
			return 1;
	}
    if(i==2)
	{
	    if(top2==StackSize)
			return 0;
	    else 
			return 1;
	}
}


### 编译原理中双栈的作用与实现 在编译原理中,双栈是一种常见的数据结构设计方法,尤其适用于涉及复杂表达式解析的任务。以下是关于双栈的具体作用以及其实现方式的详细介绍。 #### 双栈的主要作用 双栈通常用于解决具有优先级关系的操作符和操作数之间的匹配问题。具体来说,在编译过程中,当涉及到正则表达式的解析或者算术表达式的求值时,双栈能够有效地管理操作符和操作数的关系[^4]。 - **操作数**:用来存储待处理的数据项(如数值或变量名)。 - **操作符**:用来存储运算符(如 `+`, `-`, `*`, `/` 或者正则表达式中的连接、选择等符号)。 这种分离的设计使得算法能够在遇到不同类型的符号时灵活切换上下文,并按照正确的顺序执行操作。 #### 双栈的典型应用场景——正则表达式转化为NFA 在一个典型的例子中,即从正则表达式生成非确定有限自动机(NFA),双栈被广泛采用来完成这一任务。核心思想如下: 1. 将正则表达式逐步拆解为基本单元; 2. 使用一个记录当前未完成的部分NFA片段; 3. 同时利用第二个跟踪尚未处理完毕的操作符序列; 4. 当检测到高优先级的新操作符到来时,则先依据现有堆叠情况构建子图再继续推进流程直至结束[^4]。 例如,在将正则表达式 `(a|b)*abb` 转换成对应的NFA的过程中,会经历多次压入弹出动作以形成最终的状态转移网络。 #### C++ 中基于双栈的方法实例 下面展示了一个简单的C++代码示例,演示如何运用双栈机制来进行基础四则运算公式的评估: ```cpp #include <iostream> #include <stack> using namespace std; int precedence(char op){ if(op == '+'||op == '-') return 1; if(op == '*'||op == '/') return 2; return 0; } double applyOp(double b, double a, char op){ switch(op){ case '+': return a+b; case '-': return a-b; case '*': return a*b; case '/': return a/b; } } double evaluate(string tokens){ stack<double> values; // 存储数值 stack<char> ops; // 存储操作符 for(int i=0;i<tokens.length();i++){ if(tokens[i]==' ') continue; else if(isdigit(tokens[i])){ int val=0; while(i<tokens.length() && isdigit(tokens[i])) val = (val*10)+(tokens[i]-'0'), ++i; --i; values.push((double)val); } else{ while( !ops.empty() && precedence(ops.top()) >= precedence(tokens[i]) ){ double val2 = values.top(); values.pop(); double val1 = values.top(); values.pop(); char op = ops.top(); ops.pop(); values.push(applyOp(val2,val1,op)); } ops.push(tokens[i]); } } while(!ops.empty()){ double val2 = values.top(); values.pop(); double val1 = values.top(); values.pop(); char op = ops.top(); ops.pop(); values.push(applyOp(val2,val1,op)); } return values.top(); } ``` 上述代码展示了如何通过维护两个独立但相互协作的来高效地解决问题。这里特别注意的是对于每一个新加入的操作符都要考虑它相对于已存于内的其他成员之间可能存在的先后次序差异[^5]。 #### 总结 综上所述,双栈技术不仅限于理论层面的应用价值,在实际工程实践中也扮演着极其重要的角色。无论是复杂的编译器内部组件还是日常开发工具箱里的小型脚本编写环节都能见到它的身影。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值