河内迭代解决方案问题的塔楼

时间:2014-08-24 15:28:42

标签: c# loops stack pseudocode

我在解决河内之塔难题的迭代解决方案时遇到了麻烦。由于这是一项大学任务,我们已经获得了伪代码。

Towers(number, src, dest, alt)
begin
    push { number, src, dest, alt }
    while NOT stack.empty
        pop { number, src, dest, alt }
        if number = 1
            print "Move 1 disc from " + src + " to " + dest
        else
            push { number – 1, alt, dest, src }
            push { 1, src, dest, alt }
            push { number – 1, src, alt, dest }
        end-if
    end-while
end

这是我在C#中的尝试:

static void TowersIterative(uint number, char src, char dest, char alt)
{
    Stack<Move> _Stack = new Stack<Move>();

    _Stack.Push(new Move(number, src, dest, alt));
    while (_Stack.Count != 0)
    {
        _Stack.Pop();
        if (number == 1)
            Console.WriteLine("Move one disc from {0} to {1}", src, dest);
        else
        {
            _Stack.Push(new Move(number - 1, alt, dest, src));
            _Stack.Push(new Move(1, src, dest, alt));
            _Stack.Push(new Move(number - 1, src, alt, dest));
        }
    }
}

目前移动课程没有任何进展。

class Move
{
    private char _Src, _Alt, _Dest;
    private uint _Number;

    public Move(uint number, char src, char dest, char alt)
    {
        _Number = number;
        _Src = src;
        _Alt = alt;
        _Dest = dest;
    }
}

这是number = 3src = 'L'alt = 'M'dest = 'R'时所需输出的示例:

  

将一张光盘从L移动到M
  将一张光盘从L移动到R
  将一张光盘从M移动到R

目前,TowersIterative方法中的while循环无限循环,数字变量永远不等于1.

2 个答案:

答案 0 :(得分:1)

问题在于您忽略了从堆栈弹出的数据,而是使用参数,就好像它们已被弹出一样。我建议将TowersIterative分成两部分以避免这种危险:

class Move
{
    public char Src { get; private set; }
    public char Alt { get; private set; }
    public char Dest { get; private set; }
    public uint Number { get; private set; }

    public Move(uint number, char src, char dest, char alt)
    {
        Number = number;
        Src = src;
        Alt = alt;
        Dest = dest;
    }
}

public static class Hanoi
{
    static void TowersIterative(uint number, char src, char dest, char alt)
    {
        Stack<Move> _Stack = new Stack<Move>();

        _Stack.Push(new Move(number, src, dest, alt));

        TowersIterative(_Stack);
    }

    private static void TowersIterative(Stack<Move> _Stack)
    {
        while (_Stack.Count != 0)
        {
            var move = _Stack.Pop();
            if (move.Number == 1)
                Console.WriteLine("Move one disc from {0} to {1}", move.Src, move.Dest);
            else
            {
//              _Stack.Push(new Move(number - 1, alt, dest, src));
                _Stack.Push(new Move(move.Number - 1, move.Alt, move.Dest, move.Src));

//              _Stack.Push(new Move(1, src, dest, alt));
                _Stack.Push(new Move(1, move.Src, move.Dest, move.Alt));

//              _Stack.Push(new Move(number - 1, src, alt, dest));
                _Stack.Push(new Move(move.Number - 1, move.Src, move.Alt, move.Dest));
            }
        }
    }
}

我将Move中的字段更改为公共只读属性,因为这通常被认为是good programming style

答案 1 :(得分:0)

这是因为number变量有两个含义 - 一个是方法参数名称,但伪代码的意图是将它用作number的值从堆栈弹出的元素的属性。这应该有效:

static void TowersIterative(uint number, char src, char dest, char alt)
{
    var stack = new Stack<Move>();

    stack.Push(new Move(number, src, dest, alt));
    while (stack.Count != 0)
    {
        var move = stack.Pop();
        if (move.Number == 1)
            Console.WriteLine("Move one disc from {0} to {1}", move.Src, move.Dest);
        else
        {
            stack.Push(new Move(move.Number - 1, move.Alt, move.Dest, move.Src));
            stack.Push(new Move(1, move.Src, move.Dest, move.Alt));
            stack.Push(new Move(move.Number - 1, move.Src, move.Alt, move.Dest));
        }
    }
}

当然,为Move类添加适当的属性:

class Move
{
    public uint Number { get; private set; }

    public char Src { get; private set; }

    public char Dest { get; private set; }

    public char Alt { get; private set; }

    public Move(uint number, char src, char dest, char alt)
    {
        this.Number = number;
        this.Src = src;
        this.Alt = alt;
        this.Dest = dest;
    }
}

我还重命名了变量,以符合常用的约定。请参阅Working Demo