第三章 链表2.docx

上传人:b****6 文档编号:7213184 上传时间:2023-01-21 格式:DOCX 页数:26 大小:47.54KB
下载 相关 举报
第三章 链表2.docx_第1页
第1页 / 共26页
第三章 链表2.docx_第2页
第2页 / 共26页
第三章 链表2.docx_第3页
第3页 / 共26页
第三章 链表2.docx_第4页
第4页 / 共26页
第三章 链表2.docx_第5页
第5页 / 共26页
点击查看更多>>
下载资源
资源描述

第三章 链表2.docx

《第三章 链表2.docx》由会员分享,可在线阅读,更多相关《第三章 链表2.docx(26页珍藏版)》请在冰豆网上搜索。

第三章 链表2.docx

第三章链表2

3-1改写顺序栈的进栈成员函数Push(x),要求当栈满时执行一个stackFull()操作进行栈满处理。

其功能是:

动态创建一个比原来的栈数组大二倍的新数组,代替原来的栈数组,原来栈数组中的元素占据新数组的前MaxSize位置。

【解答】templatevoidstack:

:

push(constType&item){

if(isFull())stackFull();//栈满,做溢出处理

elements[++top]=item;//进栈

}

templatevoidstack:

:

stackFull(){

Type*temp=newType[3*maxSize];//创建体积大二倍的数组

for(inti=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

33232325325325632564325641

5

3

4

4

1

2

2

2

2

6

1113135********213542135426

3-3试证明:

若借助栈可由输入序列1,2,3,…,n得到一个输出序列p1,p2,p3,…,pn(它是输入序列的某一种排列),则在输出序列中不可能出现以下情况,即存在i

(提示:

用反证法)

【解答】

因为借助栈由输入序列1,2,3,…,n,可得到输出序列p1,p2,p3,…,pn,如果存在下标i,j,k,满足i

①i进栈,i出栈,j进栈,j出栈,k进栈,k出栈。

此时具有最小值的排在最前面pi位置,具有中间值的排在其后pj位置,具有最大值的排在pk位置,有pi

②i进栈,i出栈,j进栈,k进栈,k出栈,j出栈。

此时具有最小值的排在最前面pi位置,具有最大值的排在pj位置,具有中间值的排在最后pk位置,有pi

③i进栈,j进栈,j出栈,i出栈,k进栈,k出栈。

此时具有中间值的排在最前面pi位置,具有最小值的排在其后pj位置,有pj

④i进栈,j进栈,j出栈,k进栈,k出栈,i出栈。

此时具有中间值的排在最前面pi位置,具有最大值的排在其后pj位置,具有最小值的排在pk位置,有pk

⑤i进栈,j进栈,k进栈,k出栈,j出栈,i出栈。

此时具有最大值的排在最前面pi位置,具有中间值的排在其后pj位置,具有最小值的排在pk位置,有pk

0m-1

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时,栈空间满,此时不能再向任一栈加入新的元素。

试定义这种双栈(DoubleStack)结构的类定义,并实现判栈空、判栈满、插入、删除算法。

【解答】

bot[0]top[0]top[1]bot[1]

双栈的类定义如下:

#include

templateclassDblStack{//双栈的类定义

private:

inttop[2],bot[2];//双栈的栈顶指针和栈底指针

Type*elements;//栈数组

intm;//栈最大可容纳元素个数

public:

DblStack(intsz=10);//初始化双栈,总体积m的默认值为10

~DblStack(){delete[]elements;}//析构函数

voidDblPush(constType&x,inti);//把x插入到栈i的栈顶

intDblPop(inti);//退掉位于栈i栈顶的元素

Type*DblGetTop(inti);//返回栈i栈顶元素的值

intIsEmpty(inti)const{returntop[i]==bot[i];}//判栈i空否,空则返回1,否则返回0

intIsFull()const{returntop[0]+1==top[1];}//判栈满否,满则返回1,否则返回0

voidMakeEmpty(inti);//清空栈i的内容

}

templateDblStack:

:

DblStack(intsz):

m(sz),top[0](-1),bot[0](-1),top[1](sz),bot[1](sz){

//建立一个最大尺寸为sz的空栈,若分配不成功则错误处理。

elements=newType[m];//创建栈的数组空间

assert(elements!

=NULL);//断言:

动态存储分配成功与否

}

templatevoidDblStack:

:

DblPush(constType&x,inti){

//如果IsFull(),则报错;否则把x插入到栈i的栈顶

assert(!

IsFull());//断言:

栈满则出错处理,停止执行

if(i==0)elements[++top[0]]=x;//栈0情形:

栈顶指针先加1,然后按此地址进栈

elseelements[--top[1]]=x;//栈1情形:

栈顶指针先减1,然后按此地址进栈

}

templateintDblStack:

:

DblPop(inti){

//如果IsEmpty(i),则不执行退栈,返回0;否则退掉位于栈i栈顶的元素,返回1

if(IsEmpty(i))return0;//判栈空否,若栈空则函数返回0

if(i==0)top[0]--;//栈0情形:

栈顶指针减1

elsetop[1]++;//栈1情形:

栈顶指针加1

return1;

}

templateType*DblStack:

:

DblGetTop(inti){

//若栈不空则函数返回该栈栈顶元素的地址。

if(IsEmpty(inti))returnNULL;//判栈i空否,若栈空则函数返回空指针

return&elements[top[i]];//返回栈顶元素的值

}

templatevoidMakeEmpty(inti){

if(i==0)top[0]=bot[0]=-1;

elsetop[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&&!

((BD)))||(C

【解答】

(1)AB*C*

(2)A-B+C-D+

(3)AB-*C+

(4)AB+D*EFAD*+/+C+

(5)AB&&EF>!

||

(6)ABC||!

&&!

CE<||

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)-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)

若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栈,取下一符号

ab

;+

4

*

操作符

icp(‘*’)>isp(‘+’),进OPTR栈,取下一符号

ab

;+*

5

操作符

icp(‘(’)>isp(‘*’),进OPTR栈,取下一符号

ab

;+*(

6

c

操作数

c进OPND栈,取下一符号

abc

;+*(

7

-

操作符

icp(‘-’)>isp(‘(’),进OPTR栈,取下一符号

ab

;+*(-

8

d

操作数

d进OPND栈,取下一符号

abcd

;+*(-

9

操作符

icp(‘)’)

栈‘c’,退OPTR栈‘-’,计算c–d→s1,结果进

OPND栈

abs1

;+*(

10

同上

同上

icp(‘)’)==isp(‘(’),退OPTR栈‘(’,对消括号,

取下一符号

abs1

;+*

11

-

操作符

icp(‘-’)

栈‘b’,退OPTR栈‘*’,计算b*s1→s2,结果进

OPND栈

as2

;+

12

同上

同上

icp(‘-’)

栈‘a’,退OPTR栈‘+’,计算a*s2→s3,结果

进OPND栈

s3

;

13

同上

同上

icp(‘-’)>isp(‘;’),进OPTR栈,取下一符号

s3

;-

14

e

操作数

e进OPND栈,取下一符号

s3e

;-

15

操作符

icp(‘↑’)>isp(‘-’),进OPTR栈,取下一符号

s3e

;-↑

16

f

操作数

f进OPND栈,取下一符号

s3ef

;-↑

17

/

操作符

icp(‘/’)

栈‘e’,退OPTR栈‘↑’,计算e↑f→s4,结果

进OPND栈

s3s4

;-

18

同上

同上

icp(‘/’)>isp(‘-’),进OPTR栈,取下一符号

s3s4

;-/

19

g

操作数

g进OPND栈,取下一符号

s3s4g

;-/

20

;

操作符

icp(‘;’)

栈‘s4’,退OPTR栈‘/’,计算s4/g→s5,结果

进OPND栈

s3s5

;-

21

同上

同上

icp(‘;’)

栈‘s3’,退OPTR栈‘-’,计算s3–s5→s6,结

果进OPND栈

s6

;

22

同上

同上

icp(‘;’)==isp(‘;’),退OPND栈‘s6’,结束

;

3-8假设以数组Q[m]存放循环队列中的元素,同时以rear和length分别指示环形队列中的队尾位置和队列中所含元素的个数。

试给出该循环队列的队空条件和队满条件,并写出相应的插入(enqueue)和删除(dlqueue)元素的操作。

【解答】

循环队列类定义

#include

templateclassQueue{//循环队列的类定义

public:

Queue(int=10);

~Queue(){delete[]elements;}

voidEnQueue(Type&item);

TypeDeQueue();

TypeGetFront();

voidMakeEmpty(){length=0;}//置空队列

intIsEmpty()const{returnlength==0;}//判队列空否

intIsFull()const{returnlength==maxSize;}//判队列满否

private:

intrear,length;//队尾指针和队列长度

Type*elements;//存放队列元素的数组

intmaxSize;//队列最大可容纳元素个数

}

构造函数

template

Queue:

:

Queue(intsz):

rear(maxSize-1),length(0),maxSize(sz){

//建立一个最大具有maxSize个元素的空队列。

elements=newType[maxSize];//创建队列空间

assert(elements!

=0);//断言:

动态存储分配成功与否

}

插入函数

template

voidQueue:

:

EnQueue(Type&item){

assert(!

IsFull());//判队列是否不满,满则出错处理

length++;//长度加1

rear=(rear+1)%maxSize;//队尾位置进1

elements[rear]=item;//进队列

}

删除函数

template

TypeQueue:

:

DeQueue(){

assert(!

IsEmpty());//判断队列是否不空,空则出错处理

length--;//队列长度减1

returnelements[(rear-length+maxSize)%maxSize];//返回原队头元素值

}

读取队头元素值函数

template

TypeQueue:

:

GetFront(){

assert(!

IsEmpty());

returnelements[(rear-length+1+maxSize)%maxSize];//返回队头元素值

}

3-9假设以数组Q[m]存放循环队列中的元素,同时设置一个标志tag,以tag==0和tag==1来区别在队头指针(front)和队尾指针(rear)相等时,队列状态为“空”还是“满”。

试编写与此结构相应的插入(enqueue)和删除(dlqueue)算法。

【解答】

循环队列类定义

#include

templateclassQueue{//循环队列的类定义

public:

Queue(int=10);

~Queue(){delete[]Q;}

voidEnQueue(Type&item);

TypeDeQueue();

TypeGetFront();

voidMakeEmpty(){front=rear=tag=0;}//置空队列

intIsEmpty()const{returnfront==rear&&tag==0;}//判队列空否

intIsFull()const{returnfront==rear&&tag==1;}//判队列满否

private:

intrear,front,tag;//队尾指针、队头指针和队满标志

Type*Q;//存放队列元素的数组

intm;//队列最大可容纳元素个数

}

构造函数

template

Queue:

:

Queue(intsz):

rear(0),front(0),tag(0),m(sz){

//建立一个最大具有m个元素的空队列。

Q=newType[m];//创建队列空间

assert(Q!

=0);//断言:

动态存储分配成功与否

}

插入函数

template

voidQueue:

:

EnQueue(Type&item){

assert(!

IsFull());//判队列是否不满,满则出错处理

rear=(rear+1)%m;//队尾位置进1,队尾指针指示实际队尾位置

Q[rear]=item;

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 其它课程

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1