用powerbuilder实现汉诺塔的栈算法(用excel展示栈的变化过程)

栈的变化过程
3层汉诺塔求解过程, 栈的变化

 

用于保存汉诺塔的结构定义:

global type str_任务 from structure
	integer		盘子个数
	character		_起点柱
	character		中转柱
	character		目标柱
	integer		底盘序号
end type

每个汉诺塔, 都是用这个结构来保存的

用于求解的栈的类定义:

forward
global type uo_汉诺塔任务栈 from nonvisualobject
end type
end forward

global type uo_汉诺塔任务栈 from nonvisualobject autoinstantiate
end type

type variables

protectedwrite long il_栈顶
protectedwrite str_任务 i_任务栈[] 
end variables
forward prototypes
public subroutine push (str_任务 a_任务)
public function boolean pop ()
public function boolean top (ref str_任务 a_任务)
public function boolean isempty ()
end prototypes

public subroutine push (str_任务 a_任务);
il_栈顶++
i_任务栈[il_栈顶]=a_任务
end subroutine

public function boolean pop ();
if il_栈顶>0 then
	il_栈顶--
	return true
else
	return false
end if
end function

public function boolean top (ref str_任务 a_任务);
if il_栈顶>0 then
	a_任务=i_任务栈[il_栈顶]
	return true
else
	return false
end if
end function

public function boolean isempty ();
return il_栈顶=0
end function

on uo_汉诺塔任务栈.create
call super::create
TriggerEvent( this, "constructor" )
end on

on uo_汉诺塔任务栈.destroy
TriggerEvent( this, "destructor" )
call super::destroy
end on

最后是主算法求解, 利用excel来演示栈的变化过程, 非常直观

/*
	当前任务, 是指处在栈顶的汉诺塔任务															
	每个任务, 都有各自的起始柱, 中转柱, 目标柱															
																
"循环取得
栈顶的当前任务
(栈顶出栈)"	
	如果当前任务的盘子个数=1, 把任务盘, 从任务起始柱移动到任务目标柱; 重入循环起点															
	如果当前任务的盘子个数>1, 就分解为3步, 反序压入任务栈; 压入完成后重入循环起点															
					第一步(入栈):把起始柱上的,当任务的次级塔(不含最大盘的n-1个盘子), 移动到任务的中转柱											
					第二步(入栈):把起始柱上的, 剩余的1个盘子(当前任务的最大盘), 移动到当前任务的目标柱											
					第三步(入栈):把当前任务中转柱上的次级塔(不含最大盘的n-1个盘子), 移动到当前任务的目标柱											

*/
oleobject xlapp
long rtn
long cnt
string ls_filename, shorname

rtn = GetFileOpenName("选择文件", ls_filename, shorname, "xls", "xls Files (*.xls),*.xls",  '' )
IF rtn = 1 THEN
else
	return
end if

try
	xlapp = create oleobject
	rtn = xlapp.connecttonewobject("Excel.Application")

	if rtn < 0 then
		messagebox("提示","不能运行Excel程序,请检查是否已安装Microsoft Excel软件!")
	else
		xlapp.visible = true
		xlapp.workbooks.open(ls_filename)
	end if
	
	str_任务 总任务, 栈顶任务, 子任务1, 子任务2, 子任务3
	
	总任务.盘子个数=3    //用于演示,取3-5即可
	总任务._起点柱='A'
	总任务.中转柱='B'
	总任务.目标柱='C'
	总任务.底盘序号=3
	
	uo_汉诺塔任务栈 st
	
	st.push(总任务)	
	
	string ls_步骤
	long i
	
	//注意:xls文件中的演示栈是向下生长的
	constant int 起始行=11	//向xls文件写入栈内数据的起始行号, 也就是栈底行号, 
	xlapp.ActiveSheet.Cells(起始行, 1).Value="1#栈层:"+string(st.i_任务栈[1].盘子个数)+"个盘子"+st.i_任务栈[1]._起点柱+"->"+st.i_任务栈[1].目标柱+"~r~n"

	do	
		cnt++
				
		st.top(ref 栈顶任务)	//取得栈顶任务
		st.pop()	
		
		if 栈顶任务.盘子个数=1 then	//栈顶任务"可执行", 所以就只弹出, 不压入了
			ls_步骤+=string(栈顶任务.底盘序号)+"#盘: "+栈顶任务._起点柱+"->"+栈顶任务.目标柱+" 第"+string(cnt)+"次循环,(被弹出的栈顶="+string(st.il_栈顶+1)+")"+"~r~n"
		else
			//via 是中转柱 from是起始柱, to是目标柱
			//先压入栈顶的, 是第三步任务, n-1整堆v->t
			//它会被后面的任务"盖上", 下沉
			子任务3.盘子个数=栈顶任务.盘子个数 -1
			子任务3._起点柱=栈顶任务.中转柱
			子任务3.中转柱=栈顶任务._起点柱
			子任务3.目标柱=栈顶任务.目标柱
			子任务3.底盘序号=子任务3.盘子个数
			st.push(子任务3)
			
			//ls_步骤+="压入(n-1)"+string(子任务3.盘子个数)+子任务3._起点柱+"->"+子任务3.目标柱+"~r~n"
			
			//再压入的是, 第二步任务, "最大盘子"f->t
			子任务2.盘子个数=1
			子任务2._起点柱=栈顶任务._起点柱
			子任务2.目标柱=栈顶任务.目标柱
			子任务2.底盘序号=栈顶任务.底盘序号
			st.push(子任务2)
			//ls_步骤+="压入当前最大盘"+子任务2._起点柱+"->"+子任务2.目标柱+"~r~n"
			
			//最后压入的在最顶部, n-1整堆f->v
			子任务1.盘子个数=栈顶任务.盘子个数 -1
			子任务1._起点柱=栈顶任务._起点柱
			子任务1.中转柱=栈顶任务.目标柱
			子任务1.目标柱=栈顶任务.中转柱
			子任务1.底盘序号=子任务1.盘子个数
			st.push(子任务1)
			//ls_步骤+="压入(n-1)"+string(子任务1.盘子个数)+子任务1._起点柱+"->"+子任务1.目标柱+"~r~n"

		end if
		
		for i=st.il_栈顶 to 1 step -1
			xlapp.ActiveSheet.Cells(起始行 -1 +i, cnt+1).Value=string(i)+"#栈层:"+string(st.i_任务栈[i].盘子个数)+"个盘子"+st.i_任务栈[i]._起点柱+"->"+st.i_任务栈[i].目标柱+"~r~n"
		next
		
	loop  while not st.isEmpty()
	
	messagebox("",ls_步骤)
	
finally
	xlapp.disconnectobject()
	destroy xlapp
end try	

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值