这里有一个Flyweight模式 的说法,大概意思是当一个对象被反复用到时,我们可以统一创建一个对象,然后当它需要被用到时,引用这个统一的对象即可。
这个要划分外部状态和内部状态(外部状态应该就是帮助你优化算法的,它不是一个内部结构,比如当我们把非叶节点的一个左子节点设为空时,我们可以让它指向一个特殊的叶子结点,而不是设为NULL,这个特殊的叶子结点就可以理解为外部状态,大概~~~)
初始代码:
#include<iostream>
using namespace std;
#define Operand char
#define Operator char
//Node implementation with the composite design pattern 复合设计模式
class VarBinNode { //Node base class 基类
public:
virtual ~VarBinNode() {}
virtual bool isLeaf() = 0;
virtual void traverse() = 0;
};
class LeafNode :public VarBinNode { //Leaf node 叶子结点
private:
Operand var; //Operand value 运算数
public:
LeafNode(const Operand& val) { var = val; }
bool isLeaf() { return true; }
Operand value() { return var; } //Return node value
void traverse() { //叶子结点的遍历
cout << "Leaf:" << value() << endl;
}
};
class IntlNode :public VarBinNode { //Internal node 非叶子节点
private:
VarBinNode* lc; //Left child 左孩子
VarBinNode* rc; //Right child 右孩子
Operator opx; //Operator value 运算符号
public:
IntlNode(const Operator& op, VarBinNode* l, VarBinNode* r) {
opx = op;lc = l; rc = r;
}
bool isLeaf() { return false; }
VarBinNode* left() { return lc; } //Return left child左孩子
VarBinNode* right() { return rc; } //Return right child右孩子
Operator value() { return opx; } //Return operator value 运算符号
void traverse() { //非叶子结点的遍历
cout << "Internal:" << value() << endl;
if (left() != NULL)
left()->traverse();
if (right() != NULL)
right()->traverse();
}
};
//Do a preorder traversal先序遍历
void traverse(VarBinNode* root) {
if (root != NULL)root->traverse();
}
class Expressiontree { //表达式树
private:
VarBinNode* Root; //Tree root 树根
public:
Expressiontree(Operand op) { //Leaf constructor 叶子结点的构造函数
Root = new LeafNode(op);
}
//Intlnode constructor 非叶子节点的构造函数
Expressiontree(const Operator& op, Expressiontree* l, Expressiontree* r) {
Root = new IntlNode(op, l->Root, r->Root);
}
Expressiontree(VarBinNode*& node) {
Root = node;
}
void traversetree() { //遍历表达式树
traverse(Root);
}
VarBinNode* getRoot() { //获取树根结点
return Root;
}
~Expressiontree(){}
};
Expressiontree* buildtree(string s, int l, int r) {
//在创建树的时候,如果孩子节点为空,让它指向emptynode节点
if (r < l)
return NULL;
//上面这个判断条件没有必要,因为不会出现这种情况,除非错误输入,比如只输入了: "()"或者"2+"
int c1 = -1, c2 = -1;
int flag = 0;
if (r == l) { //叶子结点
return new Expressiontree(s[r]);
}
for (int i = l; i <= r; ++i) {
if (s[i] == '(')
++flag;
else if (s[i] == ')')
--flag;
else if (s[i] == '+' || s[i] == '-') {
if (flag == 0) { //说明这里的加减号在括号外,可以拿来做根结点
c1 = i;
}
}
else if (s[i] == '*' || s[i] == '/') {
if (flag == 0) {
c2 = i;
}
}
}
if (c1 < 0)c1 = c2; //如果括号外面没有加减号,用乘除号代替
if (c1 < 0)return buildtree(s, l + 1, r - 1);
Expressiontree* left = buildtree(s, l, c1 - 1);
Expressiontree* right = buildtree(s, c1 + 1, r);
Expressiontree* op = new Expressiontree(s[c1], left, right);
return op;
}
void deletetree(IntlNode*tree) { //删除表达式树,释放空间
if (tree->left() != NULL) {
if (tree->left()->isLeaf() == false) {
deletetree((IntlNode*)tree->left());
}
else
delete tree->left();
}
if (tree->right() != NULL) {
if (tree->right()->isLeaf() == false) {
deletetree((IntlNode*)tree->right());
}
else
delete tree->right();
}
delete tree;
}
int main() {
string expression = "4*x*(2*x+a)-c";
//构建表达式树
Expressiontree* expressiontree = buildtree(expression, 0, expression.size() - 1);
expressiontree->traversetree(); //遍历表达式树
deletetree((IntlNode*)expressiontree->getRoot()); //释放空间
}
优化代码
#include<iostream>
using namespace std;
#define Operand char
#define Operator char
//Node implementation with the composite design pattern 复合设计模式
class VarBinNode { //Node base class 基类
public:
virtual ~VarBinNode() {}
virtual bool isLeaf() = 0;
virtual void traverse() = 0;
};
class emptyleaf :public VarBinNode { //外部状态,其他类的代码都是内部状态
public:
bool isLeaf() { return true; }
void traverse() {
}
};
VarBinNode* emptynode = new emptyleaf();
class LeafNode :public VarBinNode { //Leaf node 叶子结点
private:
Operand var; //Operand value 运算数
public:
LeafNode(const Operand& val) { var = val; }
bool isLeaf() { return true; }
Operand value() { return var; } //Return node value
void traverse() { //叶子结点的遍历
cout << "Leaf:" << value() << endl;
}
};
class IntlNode :public VarBinNode { //Internal node 非叶子节点
private:
VarBinNode* lc; //Left child 左孩子
VarBinNode* rc; //Right child 右孩子
Operator opx; //Operator value 运算符号
public:
IntlNode(const Operator& op, VarBinNode* l, VarBinNode* r) {
opx = op;lc = l; rc = r;
}
bool isLeaf() { return false; }
VarBinNode* left() { return lc; } //Return left child左孩子
VarBinNode* right() { return rc; } //Return right child右孩子
Operator value() { return opx; } //Return operator value 运算符号
void traverse() { //非叶子结点的遍历
cout << "Internal:" << value() << endl;
//if (left() != NULL)
left()->traverse();
//if (right() != NULL)
right()->traverse();
}
};
//Do a preorder traversal先序遍历
void traverse(VarBinNode* root) {
if (root != NULL)root->traverse();
}
class Expressiontree { //表达式树
private:
VarBinNode* Root; //Tree root 树根
public:
Expressiontree(Operand op) { //Leaf constructor 叶子结点的构造函数
Root = new LeafNode(op);
}
//Intlnode constructor 非叶子节点的构造函数
Expressiontree(const Operator& op, Expressiontree* l, Expressiontree* r) {
Root = new IntlNode(op, l->Root, r->Root);
}
Expressiontree(VarBinNode*& node) {
Root = node;
}
void traversetree() { //遍历表达式树
traverse(Root);
}
VarBinNode* getRoot() { //获取树根结点
return Root;
}
~Expressiontree(){}
};
Expressiontree* buildtree(string s, int l, int r) {
//在创建树的时候,如果孩子节点为空,让它指向emptynode节点
if (r < l)
return new Expressiontree(emptynode);
//上面这个判断条件没有必要,因为不会出现这种情况,除非错误输入,比如只输入了: "()"或者"2+"
//这只是为了演示处理空指针的情况
int c1 = -1, c2 = -1;
int flag = 0;
if (r == l) { //叶子结点
return new Expressiontree(s[r]);
}
for (int i = l; i <= r; ++i) {
if (s[i] == '(')
++flag;
else if (s[i] == ')')
--flag;
else if (s[i] == '+' || s[i] == '-') {
if (flag == 0) { //说明这里的加减号在括号外,可以拿来做根结点
c1 = i;
}
}
else if (s[i] == '*' || s[i] == '/') {
if (flag == 0) {
c2 = i;
}
}
}
if (c1 < 0)c1 = c2; //如果括号外面没有加减号,用乘除号代替
if (c1 < 0)return buildtree(s, l + 1, r - 1);
Expressiontree* left = buildtree(s, l, c1 - 1);
Expressiontree* right = buildtree(s, c1 + 1, r);
Expressiontree* op = new Expressiontree(s[c1], left, right);
return op;
}
void deletetree(IntlNode*tree) { //删除表达式树,释放空间
if (tree->left()->isLeaf()==false) {
deletetree((IntlNode*)tree->left());
}
else {
if (tree->left() != emptynode) {
delete tree->left();
}
}
if (tree->right()->isLeaf() == false) {
deletetree((IntlNode*)tree->right());
}
else {
if (tree->right() != emptynode) {
delete tree->right();
}
}
delete tree;
}
int main() {
string expression = "4*x*(2*x+a)-c";
//构建表达式树
Expressiontree* expressiontree = buildtree(expression, 0, expression.size() - 1);
expressiontree->traversetree(); //遍历表达式树
deletetree((IntlNode*)expressiontree->getRoot()); //释放空间
delete emptynode; //删除外部状态(空叶节点)
}