使用堆栈解决河内塔 (java)
Using stacks to solve tower of Hanoi (java)
public static enum Action {
No, LToM, MToL, MToR, RToM
}
public static int hanoiProblem2(int num, String left, String mid, String right) {
Stack<Integer> lS = new Stack<Integer>();
Stack<Integer> mS = new Stack<Integer>();
Stack<Integer> rS = new Stack<Integer>();
lS.push(Integer.MAX_VALUE);
mS.push(Integer.MAX_VALUE);
rS.push(Integer.MAX_VALUE);
for (int i = num; i > 0; i--) {
lS.push(i);
}
Action[] record = { Action.No };
int step = 0;
while (rS.size() != num + 1) {
step += fStackTotStack(record, Action.MToL, Action.LToM, lS, mS, left, mid);
step += fStackTotStack(record, Action.LToM, Action.MToL, mS, lS, mid, left);
step += fStackTotStack(record, Action.RToM, Action.MToR, mS, rS, mid, right);
step += fStackTotStack(record, Action.MToR, Action.RToM, rS, mS, right, mid);
}
return step;
}
public static int fStackTotStack(Action[] record, Action preNoAct,
Action nowAct, Stack<Integer> fStack, Stack<Integer> tStack,
String from, String to) {
if (record[0] != preNoAct && fStack.peek() < tStack.peek()) {
tStack.push(fStack.pop());
System.out.println("Move " + tStack.peek() + " from " + from + " to " + to);
record[0] = nowAct;
return 1;
}
return 0;
}
public static void main(String[] args) {
int num = 4;
// solution 2
int steps2 = hanoiProblem2(num, "left", "mid", "right");
System.out.println("It will move " + steps2 + " steps.");
System.out.println("===================================");
}
这是解决汉诺塔的代码。它使用三个堆栈来模拟 3 个塔。
我的问题是为什么它将记录变量定义为数组?
动作[]记录={Action.No};
记录[0] = nowAct;
我试着把它们改成
动作记录=Action.No;
记录=现在行动;
然后代码无法 运行.
我不知道原因。如果有人能解释原因,我真的很感激。
谢谢
在您的示例中,record
被定义为一个数组,因为它的值在 fStackTotStack
方法中被更改。
最简单的解释是因为 Java 通过 value 传递变量,而不是 reference。它也按值传递对象引用。
以下面的代码为例:
public void foo(int bar) {
bar += 4;
System.out.println("Foo's bar: " + bar);
}
public static void main(String[] args) {
int bar = 5;
new Foo().foo(bar);
System.out.println("Main's bar: " + bar);
}
这将打印出:
Foo's bar: 9
Main's bar: 5
这是因为 foo
函数中的 bar
变量与 main
函数中的变量不同。该值只是在调用方法时复制过来。
传递数组时,变量本身还是不一样的:
public void foo(int[] bar) {
bar = new int[]{9};
System.out.println("Foo's bar: " + bar[0]);
}
public static void main(String[] args) {
int[] bar = {5};
new Foo().foo(bar);
System.out.println("Main's bar: " + bar[0]);
}
这将产生与以前相同的结果,因为 foo 的栏与 main 的栏不同。
但是,对象引用是按值传递的。这意味着虽然变量不同,但它们表示的值是相同的。因此:
public void foo(int[] bar) {
bar[0] += 4;
System.out.println("Foo's bar: " + bar[0]);
}
public static void main(String[] args) {
int[] bar = {5};
new Foo().foo(bar);
System.out.println("Main's bar: " + bar[0]);
}
将打印出与以前不同的内容:
Foo's bar: 9
Main's bar: 9
这是因为虽然 foo 的 bar
变量和 main 的 bar
变量是不同的变量,但它们指向相同的底层对象。因此,对对象本身(而不仅仅是变量)的更改将持续存在。
在上面的示例中,行 Action[] record = { Action.No };
正在创建一个数组,该数组将传递给 fStackTotStack
方法。由于变量 record
本身没有改变(任何地方都没有 record = new Action[] {}
),它指向的数组仍然是传递的那个数组。这意味着您可以更改对象本身(在本例中为数组)。
public static enum Action {
No, LToM, MToL, MToR, RToM
}
public static int hanoiProblem2(int num, String left, String mid, String right) {
Stack<Integer> lS = new Stack<Integer>();
Stack<Integer> mS = new Stack<Integer>();
Stack<Integer> rS = new Stack<Integer>();
lS.push(Integer.MAX_VALUE);
mS.push(Integer.MAX_VALUE);
rS.push(Integer.MAX_VALUE);
for (int i = num; i > 0; i--) {
lS.push(i);
}
Action[] record = { Action.No };
int step = 0;
while (rS.size() != num + 1) {
step += fStackTotStack(record, Action.MToL, Action.LToM, lS, mS, left, mid);
step += fStackTotStack(record, Action.LToM, Action.MToL, mS, lS, mid, left);
step += fStackTotStack(record, Action.RToM, Action.MToR, mS, rS, mid, right);
step += fStackTotStack(record, Action.MToR, Action.RToM, rS, mS, right, mid);
}
return step;
}
public static int fStackTotStack(Action[] record, Action preNoAct,
Action nowAct, Stack<Integer> fStack, Stack<Integer> tStack,
String from, String to) {
if (record[0] != preNoAct && fStack.peek() < tStack.peek()) {
tStack.push(fStack.pop());
System.out.println("Move " + tStack.peek() + " from " + from + " to " + to);
record[0] = nowAct;
return 1;
}
return 0;
}
public static void main(String[] args) {
int num = 4;
// solution 2
int steps2 = hanoiProblem2(num, "left", "mid", "right");
System.out.println("It will move " + steps2 + " steps.");
System.out.println("===================================");
}
这是解决汉诺塔的代码。它使用三个堆栈来模拟 3 个塔。 我的问题是为什么它将记录变量定义为数组? 动作[]记录={Action.No}; 记录[0] = nowAct;
我试着把它们改成 动作记录=Action.No; 记录=现在行动; 然后代码无法 运行.
我不知道原因。如果有人能解释原因,我真的很感激。 谢谢
在您的示例中,record
被定义为一个数组,因为它的值在 fStackTotStack
方法中被更改。
最简单的解释是因为 Java 通过 value 传递变量,而不是 reference。它也按值传递对象引用。
以下面的代码为例:
public void foo(int bar) {
bar += 4;
System.out.println("Foo's bar: " + bar);
}
public static void main(String[] args) {
int bar = 5;
new Foo().foo(bar);
System.out.println("Main's bar: " + bar);
}
这将打印出:
Foo's bar: 9
Main's bar: 5
这是因为 foo
函数中的 bar
变量与 main
函数中的变量不同。该值只是在调用方法时复制过来。
传递数组时,变量本身还是不一样的:
public void foo(int[] bar) {
bar = new int[]{9};
System.out.println("Foo's bar: " + bar[0]);
}
public static void main(String[] args) {
int[] bar = {5};
new Foo().foo(bar);
System.out.println("Main's bar: " + bar[0]);
}
这将产生与以前相同的结果,因为 foo 的栏与 main 的栏不同。
但是,对象引用是按值传递的。这意味着虽然变量不同,但它们表示的值是相同的。因此:
public void foo(int[] bar) {
bar[0] += 4;
System.out.println("Foo's bar: " + bar[0]);
}
public static void main(String[] args) {
int[] bar = {5};
new Foo().foo(bar);
System.out.println("Main's bar: " + bar[0]);
}
将打印出与以前不同的内容:
Foo's bar: 9
Main's bar: 9
这是因为虽然 foo 的 bar
变量和 main 的 bar
变量是不同的变量,但它们指向相同的底层对象。因此,对对象本身(而不仅仅是变量)的更改将持续存在。
在上面的示例中,行 Action[] record = { Action.No };
正在创建一个数组,该数组将传递给 fStackTotStack
方法。由于变量 record
本身没有改变(任何地方都没有 record = new Action[] {}
),它指向的数组仍然是传递的那个数组。这意味着您可以更改对象本身(在本例中为数组)。