是什么导致我的程序处理事情的时间超过了应有的时间?
What's causing my program to process things longer than it should?
我目前正在研究一个学校项目,该项目将解析包含不同移动说明的文本文件。然后将这些指令放置在一个树结构中,该结构总是向右分支一个新指令,向左分支每条指令可以走多少。
它将看起来像这样:
FORW
/ \
2 LEFT
/ \
90 Rep
/ \
FORW FORW
/ /
4 2
无论如何,在不深入了解我的程序细节的情况下,我的问题是我如何改进程序的这一部分以使其变得更快?
如您所见,我已尝试使用 stringbuilder 来加快该过程,但效果并没有太大不同,此时我有点不知所措,因此将不胜感激任何帮助。
这个程序已经过很多测试用例的测试,如果其中任何一个用时超过 7 秒,它就会失败,现在就是这种情况。
import java.util.ArrayList;
// Ett syntaxträd
public class CreateLines{
private boolean penDown; // 1 om pennan är nere 0 om inte.
private double x1, x2, y1, y2; // x,y-koordinat
private int degrees; // vinkel v
private String color; // nuvarande färg
private double piDegrees;
private double decimals;
private ArrayList<String> result;
public CreateLines() {
penDown = false;
x1 = 0;
x2 = 0;
y1 = 0;
y2 = 0;
degrees = 0;
color = "#0000FF";
// For optimization.
decimals = 100000;
}
public StringBuilder treeSearch (Operation tree) {
// Some variables we use down here:
double x1 = this.x1;
double y1 = this.y1;
double x2;
double y2;
int numberNode;
StringBuilder str = new StringBuilder();
switch (tree.operation) {
case FORW:
piDegrees = Math.PI*degrees/180;
numberNode = tree.evaluate();
x2 = x1 + (numberNode * Math.cos(piDegrees));
y2 = y1 + (numberNode * Math.sin(piDegrees));
x2 = (double)Math.rint(x2 * decimals) / decimals;
y2 = (double)Math.rint(y2 * decimals) / decimals;
this.x1 = x2;
this.x2 = x2;
this.y1 = y2;
this.y2 = y2;
// If penDown then we print otherwise not.
if (penDown){
str.append(color + " " + x1 + " " + y1 + " " + x2 + " " + y2 + "\n");
if(tree.right == null){
return str;
}
return str.append(treeSearch((Operation) tree.right));
}
else{
if(tree.right == null){
return str;
}
return treeSearch((Operation) tree.right);
}
case BACK:
piDegrees = Math.PI*degrees/180;
numberNode = tree.evaluate();
x2 = x1 - (numberNode * Math.cos(piDegrees));
y2 = y1 - (numberNode * Math.sin(piDegrees));
x2 = (double)Math.rint(x2 * decimals) / decimals;
y2 = (double)Math.rint(y2 * decimals) / decimals;
this.x1 = x2;
this.x2 = x2;
this.y1 = y2;
this.y2 = y2;
// If penDown then we print otherwise not.
if (penDown){
str.append(color + " " + x1 + " " + y1 + " " + x2 + " " + y2 + "\n");
if(tree.right == null){
return str;
}
return str.append(treeSearch((Operation) tree.right));
}
else{
if(tree.right == null){
return str;
}
return treeSearch((Operation) tree.right);
}
case LEFT:
numberNode = tree.evaluate();
this.degrees = degrees+numberNode;
if (penDown){
if(tree.right == null){
return str;
}
return treeSearch((Operation) tree.right);
}
else{
if(tree.right == null){
return str;
}
return treeSearch((Operation) tree.right);
}
case RIGHT:
numberNode = tree.evaluate();
this.degrees = degrees-numberNode;
if (penDown){
if(tree.right == null){
return str;
}
return treeSearch((Operation) tree.right);
}
else{
if(tree.right == null){
return str;
}
return treeSearch((Operation) tree.right);
}
case DOWN:
this.penDown = true;
if(tree.right == null){
return str;
}
return treeSearch((Operation) tree.right);
case UP:
this.penDown = false;
if(tree.right == null){
return str;
}
return treeSearch((Operation) tree.right);
case COLOR:
this.color = tree.color.toUpperCase();
if (penDown){
if(tree.right == null){
return str;
}
return treeSearch((Operation) tree.right);
}
else{
if(tree.right == null){
return str;
}
return treeSearch((Operation) tree.right);
}
case REP:
// if we got a rep instruction to the left we
if(tree.right == null){
for(int i = 0; i < tree.rep; i++){
str.append(treeSearch((Operation) tree.left));
}
return str;
}
else {
for(int i = 0; i < tree.rep; i++){
str.append(treeSearch((Operation) tree.left));
}
return str.append(treeSearch((Operation)tree.right));
}
}
assert false; // borde aldrig kunna hända
return null;
}
}
经过一番思考,正如 Tedil 和 OeterLawrey 所指出的那样,问题是我犯了一个大错误,为每次调用 treeSearch 创建了一个新的 StringBuilder,因此我的程序非常慢。我没有返回每个 Stringbuilder,而是创建了一个变量 str,然后用一个新方法将它返回给主程序,这样我就解决了问题。
感谢大家的帮助!
我目前正在研究一个学校项目,该项目将解析包含不同移动说明的文本文件。然后将这些指令放置在一个树结构中,该结构总是向右分支一个新指令,向左分支每条指令可以走多少。
它将看起来像这样:
FORW
/ \
2 LEFT
/ \
90 Rep
/ \
FORW FORW
/ /
4 2
无论如何,在不深入了解我的程序细节的情况下,我的问题是我如何改进程序的这一部分以使其变得更快?
如您所见,我已尝试使用 stringbuilder 来加快该过程,但效果并没有太大不同,此时我有点不知所措,因此将不胜感激任何帮助。
这个程序已经过很多测试用例的测试,如果其中任何一个用时超过 7 秒,它就会失败,现在就是这种情况。
import java.util.ArrayList;
// Ett syntaxträd
public class CreateLines{
private boolean penDown; // 1 om pennan är nere 0 om inte.
private double x1, x2, y1, y2; // x,y-koordinat
private int degrees; // vinkel v
private String color; // nuvarande färg
private double piDegrees;
private double decimals;
private ArrayList<String> result;
public CreateLines() {
penDown = false;
x1 = 0;
x2 = 0;
y1 = 0;
y2 = 0;
degrees = 0;
color = "#0000FF";
// For optimization.
decimals = 100000;
}
public StringBuilder treeSearch (Operation tree) {
// Some variables we use down here:
double x1 = this.x1;
double y1 = this.y1;
double x2;
double y2;
int numberNode;
StringBuilder str = new StringBuilder();
switch (tree.operation) {
case FORW:
piDegrees = Math.PI*degrees/180;
numberNode = tree.evaluate();
x2 = x1 + (numberNode * Math.cos(piDegrees));
y2 = y1 + (numberNode * Math.sin(piDegrees));
x2 = (double)Math.rint(x2 * decimals) / decimals;
y2 = (double)Math.rint(y2 * decimals) / decimals;
this.x1 = x2;
this.x2 = x2;
this.y1 = y2;
this.y2 = y2;
// If penDown then we print otherwise not.
if (penDown){
str.append(color + " " + x1 + " " + y1 + " " + x2 + " " + y2 + "\n");
if(tree.right == null){
return str;
}
return str.append(treeSearch((Operation) tree.right));
}
else{
if(tree.right == null){
return str;
}
return treeSearch((Operation) tree.right);
}
case BACK:
piDegrees = Math.PI*degrees/180;
numberNode = tree.evaluate();
x2 = x1 - (numberNode * Math.cos(piDegrees));
y2 = y1 - (numberNode * Math.sin(piDegrees));
x2 = (double)Math.rint(x2 * decimals) / decimals;
y2 = (double)Math.rint(y2 * decimals) / decimals;
this.x1 = x2;
this.x2 = x2;
this.y1 = y2;
this.y2 = y2;
// If penDown then we print otherwise not.
if (penDown){
str.append(color + " " + x1 + " " + y1 + " " + x2 + " " + y2 + "\n");
if(tree.right == null){
return str;
}
return str.append(treeSearch((Operation) tree.right));
}
else{
if(tree.right == null){
return str;
}
return treeSearch((Operation) tree.right);
}
case LEFT:
numberNode = tree.evaluate();
this.degrees = degrees+numberNode;
if (penDown){
if(tree.right == null){
return str;
}
return treeSearch((Operation) tree.right);
}
else{
if(tree.right == null){
return str;
}
return treeSearch((Operation) tree.right);
}
case RIGHT:
numberNode = tree.evaluate();
this.degrees = degrees-numberNode;
if (penDown){
if(tree.right == null){
return str;
}
return treeSearch((Operation) tree.right);
}
else{
if(tree.right == null){
return str;
}
return treeSearch((Operation) tree.right);
}
case DOWN:
this.penDown = true;
if(tree.right == null){
return str;
}
return treeSearch((Operation) tree.right);
case UP:
this.penDown = false;
if(tree.right == null){
return str;
}
return treeSearch((Operation) tree.right);
case COLOR:
this.color = tree.color.toUpperCase();
if (penDown){
if(tree.right == null){
return str;
}
return treeSearch((Operation) tree.right);
}
else{
if(tree.right == null){
return str;
}
return treeSearch((Operation) tree.right);
}
case REP:
// if we got a rep instruction to the left we
if(tree.right == null){
for(int i = 0; i < tree.rep; i++){
str.append(treeSearch((Operation) tree.left));
}
return str;
}
else {
for(int i = 0; i < tree.rep; i++){
str.append(treeSearch((Operation) tree.left));
}
return str.append(treeSearch((Operation)tree.right));
}
}
assert false; // borde aldrig kunna hända
return null;
}
}
经过一番思考,正如 Tedil 和 OeterLawrey 所指出的那样,问题是我犯了一个大错误,为每次调用 treeSearch 创建了一个新的 StringBuilder,因此我的程序非常慢。我没有返回每个 Stringbuilder,而是创建了一个变量 str,然后用一个新方法将它返回给主程序,这样我就解决了问题。
感谢大家的帮助!