Leechange请进,再请教您一下关于"堆栈以abcd顺序入栈,如何求所有合法的出栈序列"的程序(100分)

  • 主题发起人 主题发起人 iknowabc
  • 开始时间 开始时间
I

iknowabc

Unregistered / Unconfirmed
GUEST, unregistred user!
呵呵,继续拜读您的程序
堆栈以abcd顺序入栈,如何求所有合法的出栈序列
您的程序
program Project2;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
TIntegerArr = array [1..4] of Integer;
var
PopedList: TIntegerArr;
Stack: TIntegerArr;
procedure TryDoIt(PopedIndex, UnPushIndex, StackTop: Integer;
Stack: TIntegerArr);
var
i: Integer;
begin
if PopedIndex=5 then
begin
for i:=1 to 4do
Write(Chr(Ord('a')-1+PopedList), ' ');
WriteLn;
Exit
end;

if StackTop>0 then
begin
PopedList[PopedIndex]:=Stack[StackTop];
TryDoIt(PopedIndex+1, UnPushIndex, StackTop-1, Stack)
end;
if UnPushIndex<=4 then
begin
Stack[StackTop+1]:=UnPushIndex;
TryDoIt(PopedIndex, UnPushIndex+1, StackTop+1, Stack)
end;
end;

begin
TryDoIt(1, 1, 0, Stack);
ReadLn
end.
另外,任何结果字符串的子串也是合法串.
呵呵,看了您这段程序,感觉有点糊涂,有些地方不懂,请教!
1)就递归函数TryDoIt函数的几个参数而言,不是很懂:
PopedIndex:已经出栈的链表PopedList的当前位置??
UnPushIndex:待入栈元素 1234->abcd??
Stack:当前进入栈中的元素??
StackTop:栈中的当前位置??
不知道理解是否正确?
2)
if StackTop>0 then
begin
PopedList[PopedIndex]:=Stack[StackTop];
TryDoIt(PopedIndex+1, UnPushIndex, StackTop-1, Stack)
end;
if UnPushIndex<=4 then
begin
Stack[StackTop+1]:=UnPushIndex;
TryDoIt(PopedIndex, UnPushIndex+1, StackTop+1, Stack)
end;
a)这里两处TryDoIt分别是什么情况下递归?有什么作用?
b)呵呵,感觉是只要是Stack中有元素就要Pop出来
Stack中没有元素时,就将待入栈元素加入栈中,然后再Pop,如此反复。
比如:
最初的a入栈出栈,b入栈出栈,c入栈出栈,d入栈出栈,就形成了第一个出栈序列 a,b,c,d
但是后面的a,b,d,c是怎么出现的,呵呵,跟踪了一下程序,stacktop=2时,
stack怎么会是3,4,0,0,而接着PopedList变为1,2,4,4,呵呵,弄不懂了。
呵呵,看不懂这段程序,也就是无法正确理解产生的结果了。
可能我的问题很简单,还是要请LeeChange您耐心给我讲讲了。
又给您带来麻烦,实在不好意思。感谢您的帮助。

 
惭愧惭愧,自己写的程序,一时还看不懂.
 
呵呵,不急,麻烦您了。
 
关于参数的理解基本上是对的.
这题是个比较好的题目,既有栈,又有队列.字符在入栈前和出栈后都是队列.
你可以把他想象成列车在人字型的铁轨上边组.
对任何一个状态,有两种操作,1.从未入栈的数据里拿出第一个入栈.2.从栈顶出一个数据到已出栈队列的尾.
procedure TryDoIt(PopedIndex, UnPushIndex, StackTop: Integer;
Stack: TIntegerArr);
var
i: Integer;
begin
//下一出栈位为5,也就是说已经出了4个,也就是说得到了一个结果,则输出
if PopedIndex=5 then
begin
for i:=1 to 4do
Write(Chr(Ord('a')-1+PopedList), ' ');
WriteLn;
Exit
end;

//如果栈不为空,则可以出栈
if StackTop>0 then
begin
PopedList[PopedIndex]:=Stack[StackTop];
TryDoIt(PopedIndex+1, UnPushIndex, StackTop-1, Stack)
end;
//如果还有没入栈的,则入栈
if UnPushIndex<=4 then
begin
Stack[StackTop+1]:=UnPushIndex;
TryDoIt(PopedIndex, UnPushIndex+1, StackTop+1, Stack)
end;
end;

 
to LeeChange:
呵呵,程序大概流程是看懂了,但是细节方面还是不是很懂,
还是问题2中的: a,b,c,d之后,是怎么出现a,b,d,c的?栈中元素是怎么变化的?
这一点始终想不明白,还要请教一二!麻烦您了。
 
2)
if StackTop>0 then
begin
PopedList[PopedIndex]:=Stack[StackTop];
TryDoIt(PopedIndex+1, UnPushIndex, StackTop-1, Stack)
end;
if UnPushIndex<=4 then
begin
Stack[StackTop+1]:=UnPushIndex;
TryDoIt(PopedIndex, UnPushIndex+1, StackTop+1, Stack)
end;
a)这里两处TryDoIt分别是什么情况下递归?有什么作用?
1是栈不空就出栈
2是有没入栈的就入栈
b)呵呵,感觉是只要是Stack中有元素就要Pop出来
//是Stack有可能Pop就要pop出来.
Stack中没有元素时,就将待入栈元素加入栈中,然后再Pop,如此反复。
//只要有元素没有入栈,就入栈.
比如:
最初的a入栈出栈,b入栈出栈,c入栈出栈,d入栈出栈,就形成了第一个出栈序列 a,b,c,d
但是后面的a,b,d,c是怎么出现的,呵呵,跟踪了一下程序,stacktop=2时,
stack怎么会是3,4,0,0,而接着PopedList变为1,2,4,4,呵呵,弄不懂了。
呵呵,看不懂这段程序,也就是无法正确理解产生的结果了。
看递归程序有一点千万要记住,从哪里调用就返回哪里.
 
谢谢你的解答。
现在看见了递归,就习惯用您教我的栈模拟递归的方式来改改这个递归程序,但是
遇到了麻烦,
while Stack[Top].d<xxxdo
这个程序的d应该取什么值呢?
以往程序中,比如最短路径,d是四个方向,全排列中,d是各个元素,这里呢?
应该怎么改写这个程序呢?
还望得到您的帮助!
 
这题换成非递归反而罗嗦
program Project2;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
TIntegerArr = array [1..4] of Integer;
TNode = record
d: Integer;
PopedIndex: Integer;
PopedList: TIntegerArr;
UnPushIndex: Integer;
StackTop: Integer;
Stack: TIntegerArr
end;

var
Stack: array [1..10] of TNode;
Top: Integer;
NewNode: TNode;
i: Integer;
do
ne: Boolean;
begin
Top:=1;
Stack[1].d:=0;
Stack[1].PopedIndex:=1;
Stack[1].UnPushIndex:=1;
Stack[1].StackTop:=0;
FillChar(Stack[1].PopedList, SizeOf(Stack[1].PopedList), 0);
FillChar(Stack[1].Stack, SizeOf(Stack[1].Stack), 0);
while Top>0do
begin
while Stack[Top].d<2do
begin
Inc(Stack[Top].d);
do
ne:=False;
if (Stack[Top].d=1) and (Stack[Top].StackTop>0) then
begin
NewNode:=Stack[Top];
NewNode.PopedList[Stack[Top].PopedIndex]:=Stack[Top].Stack[Stack[Top].StackTop];
NewNode.PopedIndex:=Stack[Top].PopedIndex+1;
NewNode.StackTop:=Stack[Top].StackTop-1;
do
ne:=True
end
else
if (Stack[Top].d=2) and (Stack[Top].UnPushIndex<=4) then
begin
NewNode:=Stack[Top];
NewNode.StackTop:=Stack[Top].StackTop+1;
NewNode.Stack[NewNode.StackTop]:=Stack[Top].UnPushIndex;
NewNode.UnPushIndex:=Stack[Top].UnPushIndex+1;
do
ne:=True
end;
ifdo
ne then
begin
if NewNode.PopedIndex=5 then
begin
for i:=1 to 4do
Write(Chr(Ord('a')-1+NewNode.PopedList), ' ');
WriteLn
end
else
begin
NewNode.d:=0;
Inc(Top);
Stack[Top]:=NewNode
end
end
end;
Dec(Top)
end;
ReadLn
end.
 
呵呵,谢谢Leechange!
非常感谢您给予我的帮助!
 
后退
顶部