排序树节点的最佳方法?

时间:2012-01-01 06:09:26

标签: c++ sorting nodes

假设我使用node类创建了一些代码:

#include <string>
#include <vector>
using namespace std;

class node
{
    vector<node> children;
    string name;
};

并假设数据结构在内存中的大小相对较大(例如50 MiB)并且未排序。

我是否有任何合理有效的方法可以根据name 对所有节点进行排序(递归),只需创建一个新的排序树记忆然后丢弃旧副本?

关于分类的澄清:
矢量children只是根据每个元素name进行排序。没有其他因素影响排序。

(即这需要我交换两个对象而不进行深度复制 - 这在C ++ 03及更早版本中是否可行?以后怎么办?)

3 个答案:

答案 0 :(得分:3)

  

(即这需要我交换两个对象而不进行深度复制   他们 - 这在C ++ 03及更早版本中是否可行?以后怎么样?)

std::swap是标准函数。所有标准类型都提供swap操作作为成员函数。 swap对于各种算法都是非常常见和必要的。标准std::sort将使用swap来交换节点,因此您不必进行深度复制。您只需要实现swap()

class node
{
    vector<node> children;
    string name;
    void swap(node& other) {
        name.swap(other.name);
        children.swap(other.children);
    }
    void sort() {
        std::sort(children.begin(), children.end(), [&](const node& lhs, const node& rhs) {
            return lhs.name < rhs.name;
        });
        std::for_each(children.begin(), children.end(), [&](node& child) {
            child.sort();
        });
    }
};

答案 1 :(得分:1)

虽然我认为计算机模型是正确的(即std::vector<T>不能成为T的成员,因为T不完整),让我们暂时忽略它。相反,我猜你的问题是关于如何移动对象:按原样,

std::sort(children.begin(), children.end(),
               predicate);

(使用合适的谓词)将通过std::swap()交换两个节点的位置。这将创建一个深层复制和两个深度复制分配。简单的解决方法是让std::sort()使用自定义交换函数,它只是交换子向量:

class node {
    ...
public:
    void swap(node& other) {
        this->name.swap(other.name);
        this->children.swap(other.children);
    };

void swap(node& n0, node& n1) {
    n0.swap(n1);
}

通常,对于使用分配(直接或间接)的值类型,您可能希望实现swap()函数。由于正确行为不需要它,因此通常会在以后添加以获得更好的性能。

答案 2 :(得分:-2)

您可以递归遍历树并在每个节点上使用std :: sort()来重新排序节点。请参阅我已添加到节点的sort()方法。

#include <algorithm>
#include <string>
#include <vector>

class node
{
    typedef node storage_t;
    typedef std::vector<storage_t> children_t;
    children_t children;
    std::string name;

    struct by_name_fn {
        bool operator()(node const& lhs, node const& rhs) const
        {
            return lhs.name < rhs.name;
        }

        bool operator()(node const* lhs, node const* rhs) const
        {
            return lhs->name < rhs->name;
        }
    };

    void sort()
    {
        std::sort(children.begin(), children.end(), by_name_fn());
        typedef children_t::iterator iter_t;
        for (iter_t i = children.begin(), e = children.end(); i != e; ++i) {
            (*i).sort();
        }
    }
};

然而,这将进行大量的复制操作。因此,您可能需要更改节点的结构以通过引用而不是通过值包含其子节点。这是将storage_t的typedef调整为node *或某些共享指针,这取决于你的程序的其余部分。您还需要将行(* i).sort()更改为(* i) - &gt; sort()。