C++11 对特定二叉树算法使用共享ptr与唯一ptr

C++11 对特定二叉树算法使用共享ptr与唯一ptr,c++11,c++14,binary-tree,shared-ptr,unique-ptr,C++11,C++14,Binary Tree,Shared Ptr,Unique Ptr,我一直在使用智能指针而不是原始指针来实现各种二叉树算法。我对共享/唯一指针之间的差异以及何时使用这些指针有着非常深入的理解,但是这个特定的算法给我带来了很多麻烦 这是我的TreeNode实现,其左、右子级都有唯一的_ptr struct UniqueTreeNode { /*Construction via int value*/ explicit UniqueTreeNode(const int v) : val(v), left(nullptr), right(nullpt

我一直在使用智能指针而不是原始指针来实现各种二叉树算法。我对共享/唯一指针之间的差异以及何时使用这些指针有着非常深入的理解,但是这个特定的算法给我带来了很多麻烦

这是我的TreeNode实现,其左、右子级都有唯一的_ptr

struct UniqueTreeNode {

    /*Construction via int value*/
    explicit UniqueTreeNode(const int v) : val(v), left(nullptr), right(nullptr), parent(nullptr) {}

    ~UniqueTreeNode() { std::wcout << L"Destroy: " << val << std::endl; }

    /*Printing Utility for unique_ptr to tree node.*/
    friend std::wostream& operator<<(std::wostream& wout, const std::unique_ptr<UniqueTreeNode>& n) {
        std::wstringstream wss;
        print(n.get(), std::wstring(), wss, Child::LEFT);
        return wout << wss.rdbuf();
    }

    /*Printing Utility shared_ptr to tree node.*/
    friend std::wostream& operator<<(std::wostream& wout, const std::shared_ptr<UniqueTreeNode>& n) {
        std::wstringstream wss;
        print(n.get(), std::wstring(), wss, Child::LEFT);
        return wout << wss.rdbuf();
    }

    /*Printing Utility for tree node pointer.*/
    friend std::wostream& operator<<(std::wostream& wout, UniqueTreeNode* n) {
        std::wstringstream wss;
        print(n, std::wstring(), wss, Child::LEFT);
        return wout << wss.rdbuf();
    }

    /*Enum utility to pick child*/
    enum class Child { LEFT, RIGHT };
    static void print(UniqueTreeNode* n, std::wstring ws, std::wstringstream& wss, const Child& c);

    /*Construction level-by-level via vector*/
    static std::unique_ptr<UniqueTreeNode> construct(const std::vector<int>& v);

    int val; // Data element in node.
    std::unique_ptr<UniqueTreeNode> left, right; // left & right child pointers.
    UniqueTreeNode* parent; // parent raw pointer.
};


/**
* \brief Prints the tree level by level.
* \param n current node being processed.
* \param ws wide-string for storing prefix.
* \param wss appends result incrementally.
* \param c child being considered currently.
*/
inline void UniqueTreeNode::print(UniqueTreeNode* n, const std::wstring ws, std::wstringstream& wss, const Child& c) {
    if (!n) wss << L"Empty Tree";
    else {
        if (n->right) print(n->right.get(), ws + (c == Child::LEFT ? L"│   " : L"    "), wss, Child::RIGHT);
        wss << ws << (c == Child::LEFT ? L"└── " : L"┌── ") << std::to_wstring(n->val) << L"\n";
        if (n->left)  print(n->left.get(), ws + (c == Child::LEFT ? L"    " : L"│   "), wss, Child::LEFT);
    }
}

/**
* \brief Construction of tree via vector elements.
* \param v vector of elements to add.
* \return the tree after its constructed.
*/
inline std::unique_ptr<UniqueTreeNode> UniqueTreeNode::construct(const std::vector<int>& v) {
    if (v.empty()) return nullptr;
    auto it = v.cbegin();
    auto n = std::make_unique<UniqueTreeNode>(*it);
    std::queue<UniqueTreeNode*> q({ n.get() });
    while (++it != v.cend()) {
        auto *x = q.front(); q.pop();
        x->left = std::make_unique<UniqueTreeNode>(*it), q.push(x->left.get());
        if (++it == v.cend()) break;
        x->right = std::make_unique<UniqueTreeNode>(*it), q.push(x->right.get());
    }
    return n;
}
struct UniqueTreeNode{
/*通过int值构造*/
显式UniqueTreeNode(const int v):val(v)、left(nullptr)、right(nullptr)、parent(nullptr){

~UniqueTreeNode(){std::wcout使用智能指针并不禁止原始指针。在使用非拥有指针的地方,您仍然可以使用它们。在这里,我认为使用
deque s;
没有什么错。当它超出范围时,您仍然可以将所有对象干净地保存在您创建的树中。@spectras我确实尝试过这一点。但是,当我执行此操作
n->left=move(s.back());
我将无法将原始指针移动到左子对象,因为它是唯一的\u ptr。即使我能够以某种方式将子对象移动到左。由于某些原因,此操作仍然不起作用。指向n的原始指针仍然超出范围,如果我尝试添加{3,2,1}(从未进入while循环),结果并不像预期的那样。在这种情况下,我可能对指向对象的原始指针的作用域没有完全理解。它只是没有按照预期工作。
uTreeNode ConstructMaxTree(const vector<int>& v) {
    deque<uTreeNode> s;
    for (const auto val : v) {
        auto n = make_unique<UniqueTreeNode>(val);
        while (!s.empty() && s.back()->val < val) {
            n->left = move(s.back());
            s.pop_back();
        }
        if (!s.empty()) {
            s.back()->right = move(n);
        }  
        s.emplace_back(move(n));
    } 
    return move(s.front());
}