3-1改写顺序栈的进栈成员函数Push(x),要求当栈满时执行一个 stackFull()操作进行栈满处理。其功能 是:动态创建一个比原来的栈数组大二倍的新数组,代替原来的栈数组,原来栈数组中的元素占据新数组 的前 Max Size位置。 【解答】 template≤ lass Type> void stack<Iype>;push( const Type&iem){ if( isFull ())stack Full ( ∥栈满,做溢出处理 elements [++top]=item ∥进栈 template<class Type> void stack <Type>:: stackFull( Iype*temp= new Type[3* maxs ize];创建体积大二倍的数组 for( int i= 0: i<= top; i++) ∥传送原数组的数据 delete elements 删去原数组 maxSize *=3 ∥数组最大体积增长二倍 elements temp: ∥新数组成为栈的数组空间 3-2铁路进行列车调度时,常把站台设计成栈式结构的站台,如右图所示。试问: (1)设有编号为1,2,3,4,5,6的六辆列车,顺序开入栈式结构的站台,则可能 18 的出栈序列有多少种? 234 (2)若进站的六辆列车顺序如上所述,那么是否能够得到435612,325641 154623和135426的出站序列,如果不能,说明为什么不能;如果能,说明如何 得到即写出"进栈”或"出栈"的序列)。 【解答】 (1)可能的不同出栈序列有(1/6+1)*C12=132种。 不能得到435612和154623这样的出栈序列。因为若在4,3,5,6之后再将1,2出栈,则1,2必须 直在栈中,此时1先进栈,2后进栈,2应压在1上面,不可能1先于2出栈。154623也是这种情况。 出栈序列325641和135426可以得到。 3253256 32564325641 135 1354 1354213542135426 3-3试证明:若借助栈可由输入序列1,2,3,…,n得到一个输出序列p,p2,p3,…,pa(它是输入序列的某 种排列),则在输出序列中不可能出现以下情况,即存在i<j<k,使得p<pk<p。(提示:用反证法) 【解答】 因为借助栈由输入序列1,2,3,…,n,可得到输出序列pl,p, 如果存在下标i,k,满足 j<k,那么在输出序列中,可能出现如下5种情况
18 (1/(6 1)) 132 6 + C12 = 3-1 改写顺序栈的进栈成员函数 Push (x ),要求当栈满时执行一个 stackFull ( )操作进行栈满处理。其功能 是:动态创建一个比原来的栈数组大二倍的新数组,代替原来的栈数组,原来栈数组中的元素占据新数组 的前 MaxSize 位置。 【解答】template<class Type>void stack<Type> :: push ( const Type & item ) { if ( isFull ( ) ) stackFull ( ); //栈满,做溢出处理 elements [ ++top ] = item; //进栈 } template<class Type> void stack<Type> :: stackFull ( ) { Type * temp = new Type [ 3 * maxSize ]; //创建体积大二倍的数组 for ( int i = 0; i <= top; i++ ) //传送原数组的数据 temp[i] = elements[i]; delete [ ] elements; //删去原数组 maxSize *= 3; //数组最大体积增长二倍 elements = temp; //新数组成为栈的数组空间 } 3-2 铁路进行列车调度时, 常把站台设计成栈式结构的站台,如右图所示。试问: (1) 设有编号为 1,2,3,4,5,6 的六辆列车, 顺序开入栈式结构的站台, 则可能 的出栈序列有多少种? (2) 若进站的六辆列车顺序如上所述, 那么是否能够得到 435612, 325641, 154623 和 135426 的出站序列, 如果不能, 说明为什么不能; 如果能, 说明如何 得到(即写出"进栈"或"出栈"的序列)。 【解答】 (1) 可能的不同出栈序列有 种。 (2) 不能得到 435612 和 154623 这样的出栈序列。因为若在 4, 3, 5, 6 之后再将 1, 2 出栈,则 1, 2 必须 一直在栈中,此时 1 先进栈,2 后进栈,2 应压在 1 上面,不可能 1 先于 2 出栈。154623 也是这种情况。 出栈序列 325641 和 135426 可以得到。 3 5 6 2 2 4 4 4 4 1 1 1 1 1 1 1 1 3 32 32 325 325 3256 32564 325641 5 3 4 4 1 2 2 2 2 6 1 1 13 135 1354 13542 13542 135426 3-3 试证明:若借助栈可由输入序列 1, 2, 3, …, n 得到一个输出序列 p1, p2, p3, …, pn (它是输入序列的某一 种排列),则在输出序列中不可能出现以下情况,即存在 i < j < k,使得 pj < pk < pi。(提示:用反证法) 【解答】 因为借助栈由输入序列 1, 2, 3, …, n,可得到输出序列 p1, p2, p3, …, pn ,如果存在下标 i, j, k,满足 i < j < k,那么在输出序列中,可能出现如下 5 种情况:
①i进栈,i出栈,j进栈,j出栈,k进栈,k出栈。此时具有最小值的排在最前面p;位置,具有中间 值的排在其后p位置,具有最大值的排在p位置,有p<p<pk,不可能出现p<pk<p的情形 ②i进栈,i出栈,j进栈,k进栈,k出栈,j出栈。此时具有最小值的排在最前面p;位置,具有最大 值的排在p位置,具有中间值的排在最后p位置,有p<pk<p,不可能出现p<pk<p的情形; ③i进栈,j进栈,j出栈,i出栈,k进栈,k出栈。此时具有中间值的排在最前面p位置,具有最小 值的排在其后p位置,有p<p<pk,不可能出现p<pk<p1的情形; ④i进栈,j进栈,j出栈,k进栈,k出栈,i出栈。此时具有中间值的排在最前面p位置,具有最大 值的排在其后p位置,具有最小值的排在p位置,有p<p<p,也不可能出现p<pk<p1的情形 ⑤i进栈,j进栈,k进栈,k出栈,j出栈,i出栈。此时具有最大值的排在最前面p位置,具有中间 值的排在其后p位置,具有最小值的排在p位置,有p<p<p,也不可能出现p<pk<p的情形; 3-4将编号为0和1的两个栈存放于一个数组空间Ⅴm中,栈底分别处于数组的两端。当第0号栈的栈顶 指针top0等于-1时该栈为空,当第1号栈的栈顶指针top[]等于m时该栈为空。两个栈均从两端向中间 增长。当向第θ号栈插入一个新元素时,使topω增1得到新的栈顶位置,当向第1号栈插入一个新元素 时,使top[1]减1得到新的栈顶位置。当top[O]+1==top[]时或topo]==top[l]-1时,栈空间满,此时不 能再向任一栈加入新的元素。试定义这种双栈( Double stack)结构的类定义,并实现判栈空、判栈满、插入、 删除算法。 【解答】 top[OI toll bot[1] 双栈的类定义如下: #include <assert. h template <class Type> class DblStack i ∥双栈的类定义 nt top[2], bot2]; ∥双栈的栈顶指针和栈底指针 I ∥栈数组 ∥栈最大可容纳元素个数 DbIStack( int Sz=10 ) ∥初始化双栈,总体积m的默认值为10 ∥析构函数 oid DblPush( const Type& x, int 1); 把x插入到栈i的栈顶 int DblPop( int i ) ∥退掉位于栈i栈顶的元素 Type* DblGetTop( int 1) ∥返回栈i栈顶元素的值 int IsEmpty(inti) consti return top=bo;}∥判栈i空否,空则返回1,否则返回0 sFull ()const( return top[O+l ==top[1];) ∥判栈满否,满则返回1,否则返回0 ∥清空栈i的内容 template <class Type> DblStack<Type>: DblStack int Sz): m(sz), top[o](-1), bot[0J(1),top(1](sz), bot([1](sz)i ∥建立一个最大尺寸为sz的空栈,若分配不成功则错误处理 elements new Type[m]: ∥创建栈的数组空间 assert( elements I= NULL ) 断言:动态存储分配成功与否
19 ① i 进栈,i 出栈,j 进栈,j 出栈,k 进栈,k 出栈。此时具有最小值的排在最前面 pi 位置,具有中间 值的排在其后 pj 位置,具有最大值的排在 pk 位置,有 pi < pj < pk, 不可能出现 pj < pk < pi 的情形; ② i 进栈,i 出栈,j 进栈,k 进栈,k 出栈,j 出栈。此时具有最小值的排在最前面 pi 位置,具有最大 值的排在 pj 位置,具有中间值的排在最后 pk 位置,有 pi < pk < pj , 不可能出现 pj < pk < pi 的情形; ③ i 进栈,j 进栈,j 出栈,i 出栈,k 进栈,k 出栈。此时具有中间值的排在最前面 pi 位置,具有最小 值的排在其后 pj 位置,有 pj < pi < pk, 不可能出现 pj < pk < pi 的情形; ④ i 进栈,j 进栈,j 出栈,k 进栈,k 出栈,i 出栈。此时具有中间值的排在最前面 pi 位置,具有最大 值的排在其后 pj 位置,具有最小值的排在 pk 位置,有 pk < pi < pj, 也不可能出现 pj < pk < pi 的情形; ⑤ i 进栈,j 进栈,k 进栈,k 出栈,j 出栈,i 出栈。此时具有最大值的排在最前面 pi 位置,具有中间 值的排在其后 pj 位置,具有最小值的排在 pk 位置,有 pk < pj < pi, 也不可能出现 pj < pk < pi 的情形; 3-4 将编号为 0 和 1 的两个栈存放于一个数组空间 V[m]中,栈底分别处于数组的两端。当第 0 号栈的栈顶 指针 top[0]等于-1 时该栈为空,当第 1 号栈的栈顶指针 top[1]等于 m 时该栈为空。两个栈均从两端向中间 增长。当向第 0 号栈插入一个新元素时,使 top[0]增 1 得到新的栈顶位置,当向第 1 号栈插入一个新元素 时,使 top[1]减 1 得到新的栈顶位置。当 top[0]+1 == top[1]时或 top[0] == top[1]-1 时,栈空间满,此时不 能再向任一栈加入新的元素。试定义这种双栈(Double Stack)结构的类定义,并实现判栈空、判栈满、插入、 删除算法。 【解答】 双栈的类定义如下: #include <assert.h> template <class Type> class DblStack { //双栈的类定义 private: int top[2], bot[2]; //双栈的栈顶指针和栈底指针 Type *elements; //栈数组 int m; //栈最大可容纳元素个数 public: DblStack ( int sz =10 ); //初始化双栈, 总体积 m 的默认值为 10 ~DblStack ( ) { delete [ ] elements; } //析构函数 void DblPush ( const Type& x, int i ); //把 x 插入到栈 i 的栈顶 int DblPop ( int i ); //退掉位于栈 i 栈顶的元素 Type * DblGetTop ( int i ); //返回栈 i 栈顶元素的值 int IsEmpty ( int i ) const { return top[i] == bot[i]; } //判栈 i 空否, 空则返回 1, 否则返回 0 int IsFull ( ) const { return top[0]+1 == top[1]; } //判栈满否, 满则返回 1, 否则返回 0 void MakeEmpty ( int i ); //清空栈 i 的内容 } template <class Type> DblStack<Type> :: DblStack ( int sz ) : m(sz), top[0] (-1), bot[0](-1), top[1](sz), bot[1](sz) { //建立一个最大尺寸为 sz 的空栈, 若分配不成功则错误处理。 elements = new Type[m]; //创建栈的数组空间 assert ( elements != NULL ); //断言: 动态存储分配成功与否 } 0 m-1 bot[0] top[0] top[1] bot[1]
template <class Type> void DblStack<Type> DblPush( const Type& x, int i)i 如果 IsFull(),则报错:否则把x插入到栈i的栈顶 assert(!IsFull (; ∥断言:栈满则出错处理,停止执行 o[OT ∥栈0情形:栈顶指针先加1,然后按此地址进栈 else elements[--top[=x; 栈1情形:栈顶指针先减1,然后按此地址进栈 template <class Type> int DblStack<Type> :: DblPop( int 1)t 如果 IsEmpty(i),则不执行退栈,返回0:否则退掉位于栈i栈顶的元素,返回1 if( IsEmpty (i))return 0; ∥判栈空否,若栈空则函数返回0 if(i==0)top[o]-; 0情形:栈顶指针减1 else top[ 1]++; 1情形:栈顶指针加1 template <class Type> Type*DblStack<Type> DblGetTop( int i)i ∥若栈不空则函数返回该栈栈顶元素的地址 if( IsEmpty int i ))return NULL ∥判栈i空否,若栈空则函数返回空指针 return& elements[ top ∥返回栈顶元素的值 template <class Type> void Make Empty int i)& if (i=0)topo=bot[0=-1; else top[ 1]= bot[ 1]=m; 写出下列中缀表达式的后缀形式: (1)A*B*C (2)-A+B-C+D (4)(A+B)*D+E/(F+A*D)+C (5)A&&B||!(E>F)体注:按C+的优先级* (6)!(A&&!(B<C)|C>D))!C<E) 【解答】 (AB+C+ (2)A-B+C-D+ (3)AB-*C (4)AB+D*EFAD*+/+C+ (5)AB&&EF>! (6)ABC<CD>‖|!&&!CE< 3-6根据课文中给出的优先级,回答以下问题 (1)在函数 postfix中,如果表达式e含有n个运算符和分界符,问栈中最多可存入多少个元素?
20 template <class Type> void DblStack<Type> :: DblPush ( const Type& x, int i ) { //如果 IsFull ( ),则报错;否则把 x 插入到栈 i 的栈顶 assert ( !IsFull ( ) ); //断言: 栈满则出错处理,停止执行 if ( i == 0 ) elements[ ++top[0] ] = x; //栈 0 情形:栈顶指针先加 1, 然后按此地址进栈 else elements[--top[1] ] = x; //栈 1 情形:栈顶指针先减 1, 然后按此地址进栈 } template <class Type> int DblStack<Type> :: DblPop ( int i ) { //如果 IsEmpty ( i ),则不执行退栈,返回 0;否则退掉位于栈 i 栈顶的元素,返回 1 if ( IsEmpty ( i ) ) return 0; //判栈空否, 若栈空则函数返回 0 if ( i == 0 ) top[0]--; //栈 0 情形:栈顶指针减 1 else top[1]++; //栈 1 情形:栈顶指针加 1 return 1; } template <class Type> Type * DblStack<Type> :: DblGetTop ( int i ) { //若栈不空则函数返回该栈栈顶元素的地址。 if ( IsEmpty ( int i ) ) return NULL; //判栈 i 空否, 若栈空则函数返回空指针 return& elements[ top[i] ]; //返回栈顶元素的值 } template <class Type> void MakeEmpty ( int i ) { if ( i == 0 ) top[0] = bot[0] = -1; else top[1] = bot[1] = m; } 3-5 写出下列中缀表达式的后缀形式: (1) A * B * C (2) - A + B - C + D (3) A* - B + C (4) (A + B) * D + E / (F + A * D) + C (5) A && B|| ! (E > F) /*注:按 C++的优先级*/ (6) !(A && !( (B < C)||(C > D) ) )||(C < E) 【解答】 (1) A B * C * (2) A - B + C - D + (3) A B - * C + (4) A B + D * E F A D * + / + C + (5) A B && E F > ! || (6) A B C < C D > || ! && ! C E < || 3-6 根据课文中给出的优先级,回答以下问题: (1) 在函数 postfix 中,如果表达式 e 含有 n 个运算符和分界符,问栈中最多可存入多少个元素?
(2)如果表达式e含有n个运算符,且括号嵌套的最大深度为6层,问栈中最多可存入多少个元素? 【解答】 (1)在函数 postfix中,如果表达式e含有n个运算符和分界符,则可能的运算对象有n+1个。因此在 利用后缀表达式求值时所用到的运算对象栈中最多可存入n+1个元素。 (2)同上 3-7试利用运算符优先数法,画出对如下中缀算术表达式求值时运算符栈和运算对象栈的变化。 a+b*(c-d)-etf/g 【解答】 设在表达式计算时各运算符的优先规则如上一题所示。因为直接对中缀算术表达式求值时必须使用两 个栈,分别对运算符和运算对象进行处理,假设命名运算符栈为OPTR( operator的缩写),运算对象栈为 OPND(operand的缩写),下面给出对中缀表达式求值的一般规则 (1)建立并初始化OPIR栈和OPND栈,然后在OPTR栈中压入一个“; (2)从头扫描中缀表达式,取一字符送入ch。 (3)当ch不等于“;”时,执行以下工作,否则结束算法。此时在OPND栈的栈顶得到运算结果 ①如果ch是运算对象,进OPND栈,从中缀表达式取下一字符送入ch ②如果ch是运算符,比较ch的优先级 icp( ch)和OPTR栈顶运算符isp(OPTR)的优先级 若icp(ch)> isp(OPTR),则ch进OPTR栈,从中缀表达式取下一字符送入ch; 若 icp(ch)<isp(OPTR),则从OPND栈退出一个运算符作为第2操作数a2,再退出一个运算符 作为第1操作数al,从OPIR栈退出一个运算符θ形成运算指令(a)0(a2),执行结果进OPND栈 若icp(ch)==isp(OPTR)且ch==")”,则从OPTR栈退出栈顶的“(”,对消括号,然后从中缀表 达式取下一字符送入ch; 根据以上规则,给出计算a+b*(c-d)-e↑f/g时两个栈的变化。 OPND栈变化OPTR栈变化 r OPTR栈与OPND栈初始化,;进OPIR栈, 操作数 进OPND栈,取下一符号 操作符 +)>isp(;',进OPIR栈,取下一符号 操作数 b进OPND栈,取下一符号 操作符 ),进OPTR栈,取下一符号 操作符 ()>p(”)进OPR栈,取下一符号ab c进OPND栈,取下 -)>isp((),进OPIR栈,取下一符号 789 操作数d进OPND找,取下一符号 a bc d )操作符|一ip()')<ip(-),退OPND栈d,退OPND|abs 栈‘c,退OPTR栈‘-’,计算c-d→s1,结果进 OPND栈 10同上|同上 ipC))=isp((),退OPTR栈(,对消括号,abs 取下一符号 操作符ip(-”)<ip()退OPND栈's,退 OPND a sz 栈“b’,退OPTR栈‘*”,计算b*s1→s2,结果进 12同上同上 i(-”)<isp(+”),退OPND栈's2,退 OPND s3 ,退OPTR栈
21 (2) 如果表达式 e 含有 n 个运算符,且括号嵌套的最大深度为 6 层,问栈中最多可存入多少个元素? 【解答】 (1) 在函数 postfix 中,如果表达式 e 含有 n 个运算符和分界符,则可能的运算对象有 n+1 个。因此在 利用后缀表达式求值时所用到的运算对象栈中最多可存入 n+1 个元素。 (2) 同上。 3-7 试利用运算符优先数法,画出对如下中缀算术表达式求值时运算符栈和运算对象栈的变化。 a + b * (c - d) - e↑f / g 【解答】 设在表达式计算时各运算符的优先规则如上一题所示。因为直接对中缀算术表达式求值时必须使用两 个栈,分别对运算符和运算对象进行处理,假设命名运算符栈为 OPTR (operator 的缩写),运算对象栈为 OPND(operand 的缩写),下面给出对中缀表达式求值的一般规则: (1) 建立并初始化 OPTR 栈和 OPND 栈,然后在 OPTR 栈中压入一个“;” (2) 从头扫描中缀表达式,取一字符送入 ch。 (3) 当 ch 不等于“;”时,执行以下工作,否则结束算法。此时在 OPND 栈的栈顶得到运算结果。 ① 如果 ch 是运算对象,进 OPND 栈,从中缀表达式取下一字符送入 ch; ② 如果 ch 是运算符,比较 ch 的优先级 icp(ch)和 OPTR 栈顶运算符 isp(OPTR)的优先级: 若 icp(ch) > isp(OPTR),则 ch 进 OPTR 栈,从中缀表达式取下一字符送入 ch; 若 icp(ch) < isp(OPTR),则从 OPND 栈退出一个运算符作为第 2 操作数 a2,再退出一个运算符 作为第 1 操作数 a1,从 OPTR 栈退出一个运算符θ形成运算指令 (a1)θ(a2),执行结果进 OPND 栈; 若 icp(ch) == isp(OPTR) 且 ch == “)”,则从 OPTR 栈退出栈顶的“(”,对消括号,然后从中缀表 达式取下一字符送入 ch; 根据以上规则,给出计算 a + b * (c - d) - e↑f / g 时两个栈的变化。 步序 扫描项 项类型 动作 OPND 栈变化 OPTR 栈变化 0 OPTR 栈与 OPND 栈初始化, ‘;’ 进 OPTR 栈, 取第一个符号 ; 1 a 操作数 a 进 OPND 栈, 取下一符号 a ; 2 + 操作符 icp (‘ + ’ ) > isp (‘ ; ’ ), 进 OPTR 栈, 取下一符号 a ; + 3 b 操作数 b 进 OPND 栈, 取下一符号 a b ; + 4 * 操作符 icp (‘ * ’ ) > isp (‘ + ’ ), 进 OPTR 栈, 取下一符号 a b ; + * 5 ( 操作符 icp (‘ ( ’ ) > isp (‘ * ’ ), 进 OPTR 栈, 取下一符号 a b ; + * ( 6 c 操作数 c 进 OPND 栈, 取下一符号 a b c ; + * ( 7 - 操作符 icp (‘ - ’ ) > isp (‘ ( ’ ), 进 OPTR 栈, 取下一符号 a b ; + * ( - 8 d 操作数 d 进 OPND 栈, 取下一符号 a b c d ; + * ( - 9 ) 操作符 icp (‘ ) ’ ) < isp (‘ - ’ ), 退 OPND 栈 ‘d’, 退 OPND 栈 ‘c’, 退 OPTR 栈 ‘-’, 计算 c – d → s1, 结果进 OPND 栈 a b s1 ; + * ( 10 同上 同上 icp (‘ ) ’ ) == isp (‘ ( ’ ), 退 OPTR 栈‘(’, 对消括号, 取下一符号 a b s1 ; + * 11 - 操作符 icp (‘ - ’ ) < isp (‘ * ’ ), 退 OPND 栈 ‘s1’, 退 OPND 栈 ‘b’, 退 OPTR 栈 ‘*’, 计算 b * s1 → s2, 结果进 OPND 栈 a s2 ; + 12 同上 同上 icp (‘ - ’ ) < isp (‘ + ’ ), 退 OPND 栈 ‘s2’, 退 OPND 栈 ‘a’, 退 OPTR 栈 ‘+’, 计算 a * s2 → s3, 结果 s3 ;
13同上 进OPIR栈,取下一符号 e进OPND栈,取下一符号 进OPTR栈,取下一符号se 操作数一f进OPND栈,取下一符号 操作符|ip(/)<isp(↑”),退OPND栈‘f,退 OPNDs3s 栈‘e,退OPTR栈‘↑’,计算e↑f→s4,结果 进OPND栈 18同上同上一 进OPTR栈,取下一符号 桑作数 进OPND栈,取下一符号 操作符-p(;”)<p(/"),退OND栈'g,退OPND|ss 栈‘s4,退OPIR栈‘/,计算s4/g→s,结果 进OPND柱 同上同上 ip(;")<ip(-”),退OPND栈‘s,退OPND|s6 栈‘s3,退OPIR栈‘-’,计算s3 结 果进OPND栈 同上 退OPND栈‘s6,结束 3-8假设以数组Qm]存放循环队列中的元素,同时以rear和 length分别指示环形队列中的队尾位置和队列 中所含元素的个数。试给出该循环队列的队空条件和队满条件,并写出相应的插入( enq ueue)和删除( dequeue) 元素的操作 【解答】 循环队列类定义 #include <assert h> template <class Type> class Queue ∥循环队列的类定义 Queue( int10 ) Queue(i delete [elements; 3 Type DeQueue ( Type GetFront ( void Make Empty (i length =0; 3 ∥置空队列 int Is Empty (const i return length ==0; 3 ∥判队列空否 int IsFull const i return length 判队列满否 prvate /队尾指针和队列长度 Type’ elements; 存放队列元素的数组 int max Size: /队列最大可容纳元素个数 构造函数 Queue<Type>: Queue( int sz ) rear(maxSize-1), length(0), maxSize(sz)t ∥建立一个最大具有 maxSize个元素的空队列。 ∥创建队列空间 assert( elements [=0 断言:动态存储分配成功与否
22 进 OPND 栈 13 同上 同上 icp (‘ - ’ ) > isp (‘ ; ’ ), 进 OPTR 栈, 取下一符号 s3 ; - 14 e 操作数 e 进 OPND 栈, 取下一符号 s3 e ; - 15 ↑ 操作符 icp (‘↑’ ) > isp (‘ - ’ ), 进 OPTR 栈, 取下一符号 s3 e ; -↑ 16 f 操作数 f 进 OPND 栈, 取下一符号 s3 e f ; -↑ 17 / 操作符 icp (‘ / ’ ) < isp (‘↑’ ), 退 OPND 栈 ‘f’, 退 OPND 栈 ‘e’, 退 OPTR 栈 ‘↑’, 计算 e↑f → s4, 结果 进 OPND 栈 s3 s4 ; - 18 同上 同上 icp (‘ / ’ ) > isp (‘ - ’ ), 进 OPTR 栈, 取下一符号 s3 s4 ; - / 19 g 操作数 g 进 OPND 栈, 取下一符号 s3 s4 g ; - / 20 ; 操作符 icp (‘ ; ’ ) < isp (‘ / ’ ), 退 OPND 栈 ‘g’, 退 OPND 栈 ‘s4’, 退 OPTR 栈 ‘/’, 计算 s4 / g → s5, 结果 进 OPND 栈 s3 s5 ; - 21 同上 同上 icp (‘ ; ’ ) < isp (‘ - ’ ), 退 OPND 栈 ‘s5’, 退 OPND 栈 ‘s3’, 退 OPTR 栈 ‘ - ’, 计算 s3 – s5 → s6, 结 果进 OPND 栈 s6 ; 22 同上 同上 icp (‘ ; ’ ) == isp (‘ ; ’ ), 退 OPND 栈 ‘s6’, 结束 ; 3-8 假设以数组 Q[m]存放循环队列中的元素, 同时以 rear 和 length 分别指示环形队列中的队尾位置和队列 中所含元素的个数。试给出该循环队列的队空条件和队满条件, 并写出相应的插入(enqueue)和删除(dlqueue) 元素的操作。 【解答】 循环队列类定义 #include <assert.h> template <class Type> class Queue { //循环队列的类定义 public: Queue ( int=10 ); ~Queue ( ) { delete [ ] elements; } void EnQueue ( Type & item ); Type DeQueue ( ); Type GetFront ( ); void MakeEmpty ( ) { length = 0; } //置空队列 int IsEmpty ( ) const { return length == 0; } //判队列空否 int IsFull ( ) const { return length == maxSize; } //判队列满否 private: int rear, length; //队尾指针和队列长度 Type *elements; //存放队列元素的数组 int maxSize; //队列最大可容纳元素个数 } 构造函数 template <class Type> Queue<Type>:: Queue ( int sz ) : rear (maxSize-1), length (0), maxSize (sz) { //建立一个最大具有 maxSize 个元素的空队列。 elements = new Type[maxSize]; //创建队列空间 assert ( elements != 0 ); //断言: 动态存储分配成功与否