我试图将我的C++代码转换成球拍,因为我正在学习球拍。我的简化C++代码是:
struct Node
{
char value = '\0';
std::vector<Node> kids;
explicit Node(char ch) : value(ch) {}
};
void ParseTree(const std::string& tokens, size_t& i, Node& root)
{
while (i < tokens.size())
{
const Token& token = tokens[i++];
if (token == '<') // children begin
{
ParseTree(tokens, i, root.kids.back());
}
else if (token == '>') // children end, go up
{
return;
}
else
{
root.kids.emplace_back(token);
}
}
}
Node ParseTree(const std::string& s)
{
size_t i = 0;
Node root('$');
ParseTree(Parse(s), i, root);
return root;
}非常简单的代码。我对球拍的翻译是:
(define (parse-tree tokens)
(if(empty? tokens)
'()
(cond
[(eq? '< (car tokens))
(list (parse-tree (cdr tokens)))]
[(eq? '> (car tokens))
(parse-tree (cdr tokens))] ; no return, how to step up?
[else
(cons (car tokens)(parse-tree (cdr tokens)))])))这里的问题是,我不会返回(eq?'> (car令牌)),所以新的节点被添加到底部.小小的考验:
(parse-tree '(1 < 2 < 3 4 > > Z < X >))应:
'(1 (2 (3 4)) Z (X))它是:
'(1 (2 (3 4 Z (X))))怎么修呢?
发布于 2018-12-25 21:04:51
原始方法的问题在于,您试图直接移植一个命令式解决方案,该解决方案甚至使用逐个引用来跟踪遍历的状态。这是行不通的,第一步是用函数编程的方式重新考虑解决方案。
在这些问题中,我们必须跟踪嵌套结构中的位置,最好使用堆栈数据结构来解决。我将使用list来实现一个列表堆栈,下面的助手用于在最上面的列表中追加一个新元素:
(define (append-top ele stack)
(cons (append (car stack) (list ele))
(cdr stack)))现在是实际的解决方案。假设输入列表格式良好,具有相同数量的<和>,并且顺序正确(不执行错误检查):
(define (parse-tree tokens)
(let parse ([tokens tokens] [stack '(())])
(cond [(null? tokens)
; solution is at the top of the stack, return it
(car stack)]
[(eq? (car tokens) '<)
; start new sublist at the top of the stack
(parse (cdr tokens) (cons '() stack))]
[(eq? (car tokens) '>)
; pop top element of the stack, append it to previous
; frame, continue with solution where we left it
(parse (cdr tokens) (append-top (car stack) (cdr stack)))]
[else
; add current element to top of stack
(parse (cdr tokens) (append-top (car tokens) stack))])))它像预期的那样工作!
(parse-tree '(1 < 2 < 3 4 > > Z < X >))
=> '(1 (2 (3 4)) Z (X))https://stackoverflow.com/questions/53924157
复制相似问题