Java中如何使用随机数遍历数组选取随机运算符构建二叉树
实现思路
- 你的
Plus/Minus/Multi/Divide都是二叉运算符Binop的子类,randOp方法已经传入了左右子节点,只需要根据随机值返回对应运算符类的实例,把左右子节点作为构造参数传入即可 - 不要在方法内重复创建
Random对象,Random默认以系统时间戳为种子,短时间内多次创建会导致生成的随机数重复,建议在类中全局维护一个Random实例复用 - 随机生成的下标范围要和运算符数量对应,
nextInt(n)返回的是[0,n)区间的整数,4个运算符的话取值范围是0~3
关于是否需要switch-case
完全不需要强制使用,两种实现方案都可以,用数组+函数式接口的方案比switch-case可维护性更高,后续新增运算符只需要更新工厂列表即可,不需要修改分支逻辑。
修正后的代码
首先在类中添加全局的Random实例和运算符工厂列表:
import java.util.Random; import java.util.List; import java.util.function.BiFunction; public class TestArithmetic { // 全局复用Random实例 private static final Random RAND = new Random(); // 运算符工厂列表,存储各个运算符类的构造方法引用 private static final List<BiFunction<Node, Node, Binop>> OP_FACTORIES = List.of( Plus::new, Minus::new, Multi::new, Divide::new ); public static void main(String[] args) { // 测试随机生成运算符的二叉树 Node randomTree = randOp( randOp(randConst(), randConst()), randOp(randConst(), randConst()) ); System.out.println(randomTree + " = " + randomTree.eval()); // 原有测试代码保留 Node n = new Plus(new Divide(randConst(), randConst()), new Divide(randConst(), randConst())); Node nDivide = new Divide(new Plus(randConst(), randConst()), new Plus(randConst(), randConst())); Node nMulti = new Multi(new Plus(randConst(), randConst()), new Plus(randConst(), randConst())); Node nMinus = new Minus(new Plus(randConst(), randConst()), new Plus(randConst(), new Const(4.4))); System.out.println(n + " = " + n.eval()); System.out.println(nDivide + " = " + nDivide.eval()); System.out.println(nMulti + " = " + nMulti.eval()); System.out.println(nMinus + " = " + nMinus.eval()); } public static Binop randOp(Node lChild, Node rChild) { // 随机取工厂列表的下标,调用构造方法生成对应运算符实例 int opIndex = RAND.nextInt(OP_FACTORIES.size()); return OP_FACTORIES.get(opIndex).apply(lChild, rChild); } public static Const randConst() { int max = 20; int min =1; double randNum = RAND.nextInt(max-min+1) + min; return new Const(randNum); } }
如果你偏好switch-case的写法,也可以把randOp改成如下实现,效果完全一致:
public static Binop randOp(Node lChild, Node rChild) { int opIndex = RAND.nextInt(4); switch (opIndex) { case 0: return new Plus(lChild, rChild); case 1: return new Minus(lChild, rChild); case 2: return new Multi(lChild, rChild); case 3: return new Divide(lChild, rChild); default: throw new IllegalArgumentException("无效运算符索引"); } }
原有代码的问题说明
- 你原来写的
randOpNum.nextInt(4)返回值范围是03,但switch的case写的是14,完全覆盖不到正确的随机值 - 原来的方法直接返回了空的
Binop父类实例,没有返回对应运算符的子类实例,不符合多态调用的要求 - 每次调用随机方法都新建
Random实例,容易出现随机数重复的问题
内容的提问来源于stack exchange,提问作者cookielover1120
相关产品推荐
相关产品推荐

