【问题标题】:How to compare Two general tree's irrespective of the order of children nodes?无论子节点的顺序如何,如何比较两个通用树?
【发布时间】:2021-12-31 20:35:08
【问题描述】:

我有两棵通用树。那棵树的标识是它的根节点指针。表示树的数据结构是TreeNode。

struct TreeNode{
    int data;
    vector<TreeNode*> subNodes;  // list of pointers to all childNodes of particular Node
    TreeNode* parent;  // pointer to parent Node of this node
}

每棵树都由它的根节点指针标识。 我想比较两棵树,即使任何两个对应节点的子节点顺序不同,bool compareDeep(TreeNode *root1, TreeNode *root2) 也应该返回 true。

举例说明: 1)

对于这种情况, bool compareDeep(root1, root2) should return true, as order of child's differs but content is same

我可以比较精确相等的情况,我们可以一次对两棵树进行级别顺序遍历,并逐级比较节点。

实际上,我正在尝试解决由 XML 解析器返回的 XML 树的问题,我想比较两个 XML DOM 树的元素顺序。

【问题讨论】:

  • 这称为树同构。以下是这些幻灯片中的详细说明:logic.pdmi.ras.ru/~smal/files/smal_jass08_slides.pdf
  • 将节点存储在std::set&lt;int&gt; 中,并记录每个级别的节点数。 std::set 自动对数据进行排序,以便处理订单问题。请注意,这主要是算法问题,而不是 C++ 语言问题——您可以在任何其他支持结构的语言(例如 std::set)中使用相同的通用方法。
  • 鉴于std::set 本身就是一棵树,这看起来有点矫枉过正。

标签: c++ algorithm tree xml-parsing


【解决方案1】:

你可以使用std::sort函数对指针进行排序然后比较树,或者插入已经排序的数据

bool sortTreeNode(TreeNode* a, TreeNode* b) { return (*a < *b); }

std::sort(subNodes.begin(), subNodes.end(), sortTreeNode);

完整的比较和排序示例。完整版需要实现拷贝构造函数,并考虑代码的性能

我定义了两个函数sortTreeNode 对每个级别的子节点进行排序 和checkLevelTreeNode比较每一级子节点

这些函数与std::sortstd::equal 算法一起使用

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

struct TreeNode;
bool sortTreeNode(TreeNode* a, TreeNode* b);
bool checkLevelTreeNode(TreeNode* a, TreeNode* b);

struct TreeNode {
    int data;

    void Print() {
        cout << "{ ";
        for(auto & Current : subNodes) {
            cout << Current->data << " ";
        }
        cout << "}\n";

        for (auto& Current : subNodes) {
            if(Current->subNodes.size())
                Current->Print();
        }
    }

    bool compare(TreeNode& rhs) {
        if (subNodes.size() != rhs.subNodes.size() || data != rhs.data)
            return false;

        sort(subNodes.begin(), subNodes.end(), sortTreeNode);
        sort(rhs.subNodes.begin(), rhs.subNodes.end(), sortTreeNode);


        if (equal(subNodes.begin(), subNodes.end(), rhs.subNodes.begin(), checkLevelTreeNode)) {
            auto Lh = subNodes.begin();
            auto Rh = rhs.subNodes.begin();

            while (Lh != subNodes.end()) {
                if (!(*Lh)->compare(*(*Rh)))
                    return false;
                Lh++; Rh++;
            }
        }
        else
            return false;

        return true;
    }

    ~TreeNode() {
        for (auto & Current : subNodes)
            delete Current;

        subNodes.clear();

        parent = nullptr;
    }

    vector<TreeNode*> subNodes;  // list of pointers to all childNodes of particular Node
    TreeNode* parent = nullptr;  // pointer to parent Node of this node
};

bool sortTreeNode(TreeNode* a, TreeNode* b) {
    return (a->data < b->data);
}

bool checkLevelTreeNode(TreeNode* a, TreeNode* b) {
    return a->data == b->data;
}


int main()
{
    int size1 = 3;
    int size2 = 3;

    TreeNode Main1 { 1 };
    TreeNode Main2 { 1 };

    for (int i = 0; i < size1; i++) {
        TreeNode * ptr1 = new TreeNode{ i };
        TreeNode * ptr2 = new TreeNode{ size1 -1 -i };

        ptr1->parent = &Main1;
        Main1.subNodes.push_back(ptr1);

        ptr2->parent = &Main2;
        Main2.subNodes.push_back(ptr2);

        for (int j = 0; j < size2; j++) {
            TreeNode* ptr3 = new TreeNode{ j };
            TreeNode* ptr4 = new TreeNode{ size2 -1 -j };

            ptr3->parent = ptr1;
            ptr1->subNodes.push_back(ptr3);

            ptr4->parent = ptr2;
            ptr2->subNodes.push_back(ptr4);
        }
    }
    cout << "Main1\n";
    Main1.Print();
    cout << "Main2\n";
    Main2.Print();

    cout << "Compare: " << (Main1.compare(Main2) ? "True" : "False") << endl;

    cout << "Main1\n";
    Main1.Print();
    cout << "Main2\n";
    Main2.Print();

    return 0;
}

输出

Main1
{ 0 1 2 }
{ 0 1 2 }
{ 0 1 2 }
{ 0 1 2 }
Main2
{ 2 1 0 }
{ 2 1 0 }
{ 2 1 0 }
{ 2 1 0 }
Compare: True
Main1
{ 0 1 2 }
{ 0 1 2 }
{ 0 1 2 }
{ 0 1 2 }
Main2
{ 0 1 2 }
{ 0 1 2 }
{ 0 1 2 }
{ 0 1 2 }

【讨论】:

    猜你喜欢
    • 2019-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多