Algorithm 实现迭代的单堆栈二叉树复制函数

Algorithm 实现迭代的单堆栈二叉树复制函数,algorithm,data-structures,binary-tree,binary-search-tree,Algorithm,Data Structures,Binary Tree,Binary Search Tree,作为一个思想练习,我试图实现一个迭代树(二进制或二进制搜索树)复制函数 我的理解是,这可以通过微不足道的方式实现: 单叠 不使用包装器(包含对副本和原始节点的引用) 如果节点没有对其父节点的引用(节点中的父节点引用是否与树的真实定义(我认为是DAG)相反?) 我已经编写了不同的实现来满足上述约束的相反要求,但是我不确定如何利用这些约束来解决问题 我没有在算法4/e中看到任何东西,也没有在网上看到任何东西(除了关于它是多么微不足道的声明)。我考虑过使用当前/以前var的顺序和顺序后的概念,但在

作为一个思想练习,我试图实现一个迭代树(二进制或二进制搜索树)复制函数

我的理解是,这可以通过微不足道的方式实现:

  • 单叠
  • 不使用包装器(包含对副本和原始节点的引用)
  • 如果节点没有对其父节点的引用(节点中的父节点引用是否与树的真实定义(我认为是DAG)相反?)
我已经编写了不同的实现来满足上述约束的相反要求,但是我不确定如何利用这些约束来解决问题

我没有在算法4/e中看到任何东西,也没有在网上看到任何东西(除了关于它是多么微不足道的声明)。我考虑过使用当前/以前var的顺序和顺序后的概念,但在弹出堆栈时,我没有看到准确跟踪的方法。我还简要考虑了一个散列映射,但我觉得这仍然只是额外的存储,就像额外的堆栈一样

我非常感谢您在理解我没有看到的方法背后的概念/习惯用法方面提供的任何帮助

提前谢谢

编辑:

到目前为止我试过的一些请求。这里是2栈解决方案,我相信它应该能够最简单地转化为1栈

<>这是用C++编写的。我是新的语言(但不是编程),并用C++入门5 / E(Lippman,Lajole,MOO)[C++ 11 ]和互联网来教我自己。如果从语言的角度来看有任何代码是错误的,请让我知道(尽管我知道代码复查堆栈交换是进行实际复查的地方)

我有一个模板节点,供代码的其他部分使用

template<typename T>
struct Node;

typedef Node<std::string> tree_node;
typedef std::shared_ptr<tree_node> shared_ptr_node;

template<typename T>
struct Node final {

public:
    const T value;
    const shared_ptr_node &left = m_left;
    const shared_ptr_node &right = m_right;

    Node(const T value, const shared_ptr_node left = nullptr, const shared_ptr_node right = nullptr) : value(value), m_left(left), m_right (right) {}

    void updateLeft(const shared_ptr_node node) {
        m_left = node;
    }

    void updateRight(const shared_ptr_node node) {
        m_right = node;
    }

private:
    shared_ptr_node m_left;
    shared_ptr_node m_right;
};
模板
结构节点;
typedef节点树\ u节点;
typedef std::shared_ptr shared_ptr_节点;
模板
结构节点最终{
公众:
常数T值;
const shared_ptr_node&left=m_left;
const shared_ptr_node&right=m_right;
节点(const T value,const shared_ptr_Node left=nullptr,const shared_ptr_Node right=nullptr):值(value),m_left(left),m_right(right){
void updateLeft(常量共享\u ptr\u节点){
m_左=节点;
}
void updateRight(常量共享\u ptr\u节点){
m_right=节点;
}
私人:
共享节点m_左;
共享ptr_节点m_权限;
};
然后是2栈实现

shared_ptr_node iterativeCopy2Stacks(const shared_ptr_node &node) {

    const shared_ptr_node newRoot = std::make_shared<tree_node>(node->value);

    std::stack<const shared_ptr_node> s;
    s.push(node);

    std::stack<const shared_ptr_node> copyS;
    copyS.push(newRoot);

    shared_ptr_node original = nullptr;
    shared_ptr_node copy = nullptr;

    while (!s.empty()) {

        original = s.top();
        s.pop();

        copy = copyS.top();
        copyS.pop();

        if (original->right) {
            s.push(original->right);

            copy->updateRight(std::make_shared<tree_node>(original->right->value));
            copyS.push(copy->right);
        }

        if (original->left) {
            s.push(original->left);

            copy->updateLeft(std::make_shared<tree_node>(original->left->value));
            copyS.push(copy->left);
        }
    }

    return newRoot;
}
shared_ptr_节点迭代copy2stack(const shared_ptr_节点和节点){
const shared\u ptr\u node newRoot=std::make\u shared(node->value);
std::堆栈s;
s、 推送(节点);
std::堆栈副本;
copyS.push(newRoot);
共享_ptr_node original=nullptr;
共享\u ptr\u节点副本=空ptr;
而(!s.empty()){
原始=s.顶部();
s、 pop();
copy=copyS.top();
copyS.pop();
如果(原始->右侧){
s、 推送(原始->右侧);
复制->更新权利(标准::使共享(原始->权利->价值));
复制。推送(复制->右);
}
如果(原始->左){
s、 推送(原稿->左);
复制->更新(标准::使_共享(原始->左->值));
复制。推送(复制->左);
}
}
返回newRoot;
}

<>我不精通C++,所以你必须用伪代码解决:

node copy(treenode n):
    if n == null
        return null

    node tmp = clone(n) //no deep clone!!!

    stack s
    s.push(tmp)

    while !s.empty():
        node n = s.pop()

        if n.left != null:
            n.left = clone(n.left)
            s.push(n.left)
        if n.right != null:
            n.right = clone(n.right)
            s.push(n.right)

    return tmp
请注意,
clone(node)
不是深度克隆。基本思想是从根的浅层克隆开始,然后迭代该节点的所有子节点,并用浅层副本替换这些节点(仍然引用原始节点),替换这些节点的子节点,等等。。该算法以DFS方式遍历树。如果您喜欢BFS(无论出于何种原因),您可以用队列替换堆栈。这段代码的另一个优点是:只需稍作修改,就可以对任意树进行修改

此算法的递归版本(如果您更喜欢递归代码而不是我的prosa):

编辑:

如果您想查看工作代码,我已经在python中创建了一个。您能告诉我们您尝试了什么吗?您有复制函数的递归版本吗?如果是,请在问题中包括它。在第二种情况下,“包装器”的确切含义是什么?我们允许在堆栈中存储什么类型的信息?请注意,a不是。说“树(B或BST)”是。。。有点不稳定。你是说“二叉树还是二叉搜索树?”谢谢你的浅显复制思想,也谢谢你的伪代码和实代码的额外步骤。@GoodEgg很乐意帮忙;)。既然你是新来的:如果这个答案解决了你的问题,考虑一下。谢谢。对于我最初的问题,我有几个答复,所以我将等待一段时间来接受答案-但是考虑到数据结构的限制,我相信您建议的方法是正确的。
node copyRec(node n):
    if n.left != null:
        n.left = clone(n.left)
        copyRec(n.left)

    if n.right != null:
        n.right = clone(n.right)
        copyRec(n.right)

    return n

node copy(node n):
    return copyRec(clone(n))