需要帮助生成C++深度有限的随机表达式树

Need help generating random expression tree with limited depth in C++

本文关键字:随机 表达式 深度 帮助 C++      更新时间:2023-10-16

我找到了这个例子: 在表达式树中插入节点并进行了一些小的修改:

class Node {
public:
std::string data;
Node* left, * right;
Node* parent; // operator
Node(std::string d, Node* p) : data(d), left(NULL), right(NULL), parent(p) {}
};
class ExpressionTree {
public:
Node* root;
int tsize;
ExpressionTree() : root(NULL), tsize(0) {}
void insert(string s);
bool isOperator(string value);
};
bool ExpressionTree::isOperator(string value) {
if (value == "+" || value == "-" ||
value == "*" || value == "/" ||
value == "==")
return true;
return false;
}
void ExpressionTree::insert(std::string s) {
if (root == NULL) {
root = new Node(s, NULL);
++tsize;
}
else {
Node* current = root;
while (true) {
if (isOperator(current->data)) {
if (current->left == NULL) {
current->left = new Node(s, current);
++tsize;
return;
}
else if (current->right == NULL) {
current->right = new Node(s, current);
//++tsize;
return;
}
else {
if (isOperator(current->left->data)) {
current = current->left;
continue;
}
else if (isOperator(current->right->data)) {
current = current->right;
continue;
}
else {
if (current->parent) {
current = current->parent->right;
continue;
}
else {
//std::cout << "Error: only nodes who hold operators "
//  << "can have children." << std::endl;
return;
}
}
}
}
else {
//std::cout << "Error: only nodes who hold operators "
//  << "can have children." << std::endl;
return;
}
}
}
}
void inorder(Node* node) {
if (node) {
if (node->left && node->parent)
cout << "(";
inorder(node->left);
cout << node->data;
inorder(node->right);
if (node->right && node->parent)
cout << ")";
}
}

我需要的是基于输入向量创建深度有限的随机表达式树

int maxDepth = 2;
vector<string> operands = { "A", "B", "C" };
vector<string> operators = { "+", "*", "-" };

如果可以实现这样的事情,那就太好了:

ExpressionTree expression = generateRandomTree(operands, operators, maxDepth);

在这种情况下,可能的顺序解是ABC(树深度= 1(或A + BA - AC - A等,如果树深度>1。

与上一个链接一样,要使表达式有效,必须应用以下规则:

  • 每个节点有零个、一个或两个子节点。
  • 只有包含运算符的节点才能有子节点。
  • 所有叶节点都必须是操作数。

方法insert做得很好,但我根本不知道如何基于此代码生成随机表达式树。感谢您帮助解决此问题。

编辑:大声思考,我可能应该用随机操作数或随机运算符(50-50% 的机会(重复执行insert,直到所有叶节点都成为操作数或达到最大深度。此外,我只需要强制maxDepth树级别的随机操作数(如果达到(。尽管如此,实施仍然是我遇到的问题。

我想我做到了...至少结果看起来不错。

#include <iostream> 
#include <string> 
#include <vector> 
#include <ctime>
using namespace std;
class Node {
public:
string data;
string type;
Node* left, * right;
Node* parent; // operator
Node(string d, string t) : data(d), type(t), left(NULL), right(NULL), parent(NULL) {}
};
class ExpressionTree {
public:
Node* root;
int tsize;
ExpressionTree() : root(NULL), tsize(0) {}
//void insert(string s);
void addLeafNode(Node* node);
bool isOperator(string value);
};
bool ExpressionTree::isOperator(string value) {
if (value == "+" || value == "-" ||
value == "*" || value == "/" ||
value == "==")
return true;
return false;
}
void inorder(Node* node) {
if (node) {
if (node->left && node->parent)
cout << "(";
inorder(node->left);
cout << node->data;
inorder(node->right);
if (node->right && node->parent)
cout << ")";
}
}
void randomOperandOrOperator(vector<string> operands, vector<string> operators, string* value, string* type, bool maxDepth) {
if (!operators.size())
maxDepth = 1;
if (maxDepth == 1) {
*value = operands[rand() % operands.size()];
*type = "operand";
}
else {
int percentage = rand() % 100 + 1;
if (percentage <= 50) {
*value = operands[rand() % operands.size()];
*type = "operand";
}
else {
*value = operators[rand() % operators.size()];
*type = "operator";
}
}
}
Node* getFirstFreeOperatorLeafNode(Node* root) {
Node* res = NULL;
if (root == NULL)
return NULL;
if (root->type == "operator") {
if (root->left == NULL || root->right == NULL)
return root;
if(root->left != NULL)
res = getFirstFreeOperatorLeafNode(root->left);
if (res == NULL && root->right != NULL)
res = getFirstFreeOperatorLeafNode(root->right);
}
return res;
}
void ExpressionTree::addLeafNode(Node* node) {
// tree is empty?
if (root == NULL) {
root = node;
node->parent = NULL;
node->left = NULL;
node->right = NULL;
}
else {
// add new node to first free operator leaf node
Node* lastOperatorLeaf = getFirstFreeOperatorLeafNode(root);
if (lastOperatorLeaf != NULL) {
if (lastOperatorLeaf->left == NULL) {
lastOperatorLeaf->left = node;
node->parent = lastOperatorLeaf->left;
}
else
if (lastOperatorLeaf->right == NULL) {
lastOperatorLeaf->right = node;
node->parent = lastOperatorLeaf->right;
}
}
}
}
int getDepth(Node* node){
if (node == NULL)
return 0;
else{
int lDepth = getDepth(node->left);
int rDepth = getDepth(node->right);
if (lDepth > rDepth)
return(lDepth + 1);
else return(rDepth + 1);
}
}
int main() {
srand(time(NULL));
vector<string> operands = { "A", "B", "C" };
vector<string> operators = { "+", "*", "-" };
int maxDepth = 5;
for (int i = 0; i < 5; i++) {
ExpressionTree expression;
do {
string value, type;
randomOperandOrOperator(operands, operators, &value, &type, (getDepth(expression.root) + 1 >= maxDepth));
expression.addLeafNode(new Node(value, type));
} while (getFirstFreeOperatorLeafNode(expression.root) != NULL);
cout << i + 1 << ". depth: " << getDepth(expression.root) << " => ";
inorder(expression.root);
cout << endl;
}
return 0;
}

5 个样品用于maxDepth = 5

  1. 深度: 2 => B * A
  2. 深度: 4 => ((B - A( * A( * (A * C(
  3. 深度: 5 => ((C - C( - A( + (B + B(( * C
  4. 深度: 1 => C
  5. 深度: 1 => A

我希望这对某人有用,或者如果有什么需要修复,请告诉我。

只是在树中随机插入东西是行不通的。从 2 开始的幂maxDepth运算符的可能性有限,因此没有更多的操作数空间。

您要做的是从节点开始,如果它在maxDepth处,请始终选择一个操作数,否则随机选择一个运算符或操作数。如果选择了运算符,则对左右子项递归重复此操作。

如果树的深度必须正好maxDepth,那么你将需要进一步修改这个算法。