让我们使用示例树来遵循执行流程。
和
/ \
左或右或
/\/\
X=6 Z=9 T=6 H=8
< /代码>
当我们退出第一个whileloop时,我们的堆栈如下:
stack=
ComparatorStack=和,Leftor,Rightor
specstack=x=6,z=9,t=6,h=8_
< /代码>
相同的状态进入最终状态while
loop.
while(!ComparatorStack.Empty()){
searchOperationRequest searchOperationRequest=comparatorstack.pop();
规格<u>operand1=specstack.pop();
规格<U>operand2=specstack.pop();
if(searchOperationRequest.getComparator().equals(searchComparator.and))。{
specstack.push(规范.where(operand1)
.和(操作2));
}否则,如果(searchOperationRequest.getComparator().equals(searchComparator.or))。{
specstack.push(规范.where(operand1)
或(操作数2);
}
}
< /代码>
这里的问题是您将结果推回到specstack。因此,在第二次迭代时,您将弹出第一次迭代的结果(therightor),以及z=9,并将leftorlogic应用到它。
分解树
让我们后退一步,看看你是如何分解树的,更具体地说:
if(pointer.getLeft()!{NULL){
pointer.setright(pointer.getleft());
pointer.setleft(空);
否则,(如果)!stack.empty()){
searchOperationRequest temp=stack.pop();
指针。设置正确(温度);
}
< /代码>
此代码的问题在于您正在更改树中的节点。在第一个示例中,我们的指针一次指向节点:
z=9
/ \
零右位
< /代码>
看起来不太对劲。不要使用堆栈(depth first search)来分解树,您可以使用队列(width first search)并获取您在进行免费订购后的订单。
![](“https://i.stack.imgur.com/mzllv.png”alt=“bfs”/)
这是否解决了将每个逻辑运算符(comparator)应用于正确操作数的问题?不完全如此,为了能够解决下面的两种布局,我们可以在不同的工作流中分解运算符和操作数,而不是将它们全部分解在一起。
and rootand
/\|/\
左或右或左或右或
/\/\|/\/\
X=6 Z=9 T=6 H=8_X=6 Z=9 H=8
|/\
| t=6 y=3
< /代码>
解决方案
本文中第一个类似JSON的表示有一个不合逻辑的布局,因为逻辑运算符需要同时操作左操作数和右操作数。相反,你有:
“right”:。{
“左”:{
“列”:“X”,
“condition”:“等于”,
“价值”:88
}
“comparator”:“和”
}
< /代码>
让我们考虑对称表示的解决方案,其中每个逻辑运算符都有左操作数和右操作数。
首先,我们对树进行逐级处理。同时,我们将每个comparator放在一个堆栈上,这样我们在第二个whileloop中首先得到最后一个。
在第二个循环中,当我们返回到根目录时,我们使用一个新的队列
来存储我们的“in between results”。
queue<searchOperationRequest>queue=new linkedList<gt;();
deque<searchOperationRequest>comparatorStack=新建链接列表<>();
如果(根==空!root.iscomparator())返回;
queue.add(根);
而(!)queue.isEmpty()){
searchOperationRequest节点=queue.poll();
comparatorstack.push(节点);
如果(没有)离开!=空&&node.left.iscomparator())queue.add(node.left);
如果(没错)!=空&node.right.iscomparator())queue.add(node.right);
}
queue<规范>specqueue=new linkedList<>();
而(!)comparatorstack.isEmpty()){
searchOperationRequest comparator=comparatorstack.pop();
//颠倒操作数顺序,以便正确轮询已计算的值
规范操作2;
searchOperationRequest指针=comparator.getRight();
if(pointer.istreeeaf()){
operand2=converter.apply(new specificationsearchcriteria(pointer.getColumn(),pointer.getCondition(),pointer.getValue());
}否则{
operand2=specqueue.poll();
}
规范操作1;
指针=comparator.getLeft();
if(pointer.istreeeaf()){
operand1=converter.apply(new specificationsearchcriteria(pointer.getColumn(),pointer.getCondition(),pointer.getValue());
}否则{
operand1=specqueue.poll();
}
if(comparator.equals(searchcomparator.and))。{
specqueue.add(specification.where(operand1).and(operand2));
}否则,如果(comparator.equals(searchcomparator.or))。{
while
stack = {}
comparatorStack = { AND, leftOR, rightOR }
specStack = { X=6, Z=9, T=6, H=8 }
while (!comparatorStack.empty()) {
SearchOperationRequest searchOperationRequest = comparatorStack.pop();
Specification<U> operand1 = specStack.pop();
Specification<U> operand2 = specStack.pop();
if (searchOperationRequest.getComparator().equals(SearchComparator.AND)) {
specStack.push(Specification.where(operand1)
.and(operand2));
} else if (searchOperationRequest.getComparator().equals(SearchComparator.OR)) {
specStack.push(Specification.where(operand1)
.or(operand2));
}
}
specStack
rightOR
Z=9
leftOr
if (pointer.getLeft() != null) {
pointer.setRight(pointer.getLeft());
pointer.setLeft(null);
} else if (!stack.empty()) {
SearchOperationRequest temp = stack.pop();
pointer.setRight(temp);
}
Z=9
/ \
null rightOR
Depth First SearchBreadth First Search
![BFS](https://i.stack.imgur.com/MZllV.png)
comparator
AND | rootAND
/ \ | / \
leftOR rightOR | leftOR rightOR
/ \ / \ | / \ / \
X=6 Z=9 T=6 H=8 | X=6 AND Z=9 H=8
| / \
| T=6 Y=3
"right": {
"left": {
"column": "X",
"condition": "EQUALS",
"value": 88
},
"comparator": "AND"
}
Queue
Queue<SearchOperationRequest> queue = new LinkedList<>();
Deque<SearchOperationRequest> comparatorStack = new LinkedList<>();
if (root == null || !root.isComparator()) return;
queue.add(root);
while(!queue.isEmpty()){
SearchOperationRequest node = queue.poll();
comparatorStack.push(node);
if(node.left != null && node.left.isComparator()) queue.add(node.left);
if(node.right != null && node.right.isComparator()) queue.add(node.right);
}
Queue<Specification> specQueue = new LinkedList<>();
while(!comparatorStack.isEmpty()){
SearchOperationRequest comparator = comparatorStack.pop();
// reverse operand order so already computed values are polled correctly
Specification operand2;
SearchOperationRequest pointer = comparator.getRight();
if(pointer.isTreeLeaf()) {
operand2 = converter.apply(new SpecificationSearchCriteria(pointer.getColumn(), pointer.getCondition(), pointer.getValue()));
} else {
operand2 = specQueue.poll();
}
Specification operand1;
pointer = comparator.getLeft();
if(pointer.isTreeLeaf()) {
operand1 = converter.apply(new SpecificationSearchCriteria(pointer.getColumn(), pointer.getCondition(), pointer.getValue()));
} else {
operand1 = specQueue.poll();
}
if (comparator.equals(SearchComparator.AND)) {
specQueue.add(Specification.where(operand1).and(operand2));
} else if (comparator.equals(SearchComparator.OR)) {
specQueue.add(Specification.where(operand1).or(operand2));
}
}
return specQueue.poll();