遍历n个节点能够形成的所有二叉树

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 20:56   2089   0

帮师兄做的一个问题,就是求对n个不同节点能够形成所有的二叉树的形式,不考虑旋转对称性和同构

问题描述:给定n个节点,查看能够有多少种不同的二叉树形成,并输出出来

算法描述:使用最基本的“分治法“(Divide and Conquer)思想,任选一个节点作为根节点,将剩余节点组成的集合进行分割(Partition),一部分放到左子树进行递归,另一部分放到右子树递归。重点为两部分:一部分使用二进制对集合进行分割,其实就是就集合的”幂集“,另一部分是如何存储。另外还可以进行暴力搜索。

测试用例:n=3,能够形成30种不同二叉树。

代码:

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

vector< string > generate_tree(const vector< string > &nodes) {
    if (nodes.empty()) {
        return vector< string >{"*"};
    } else if (1 == nodes.size()) {
        return vector< string >{nodes[0]};
    }
    vector< string > trees, tmp, left, right, l_tree, r_tree;
    for (size_t i = 0; i < nodes.size(); ++i) {
        tmp = nodes;
        tmp.erase(tmp.begin() + i);
        for (size_t j = 0; j < 1<<tmp.size(); ++j) {  // do set partition
            left.clear();
            right.clear();
            for (size_t k = 0; k < tmp.size(); ++ k) {
                if (!(j & (1<<k))) {
                    left.push_back(tmp[k]);
                } else {
                    right.push_back(tmp[k]);
                }
            }
            l_tree = generate_tree(left);
            r_tree = generate_tree(right);
            for (const string &l : l_tree) {
                for (const string &r : r_tree) {
                    trees.push_back(nodes[i] + "(" + l + "," + r + ")");
                }
            }
        }
    }
    return trees;
}

int main() {
    vector< string > nodes{"A", "B", "C"};
    vector< string > trees = generate_tree(nodes);
    cout << trees.size() << endl;
    for (auto &i : trees) {
        cout << i << endl;
    }
    return 0;
}

由于使用c++11的特性,所以文件的编译命令为

g++ -std=c++11 generate_tree.cc

输出结果为
30
A(B(C,*),*)
A(B(*,C),*)
A(C(B,*),*)
A(C(*,B),*)
A(C,B)
A(B,C)
A(*,B(C,*))
A(*,B(*,C))
A(*,C(B,*))
A(*,C(*,B))
B(A(C,*),*)
B(A(*,C),*)
B(C(A,*),*)
B(C(*,A),*)
B(C,A)
B(A,C)
B(*,A(C,*))
B(*,A(*,C))
B(*,C(A,*))
B(*,C(*,A))
C(A(B,*),*)
C(A(*,B),*)
C(B(A,*),*)
C(B(*,A),*)
C(B,A)
C(A,B)
C(*,A(B,*))
C(*,A(*,B))
C(*,B(A,*))
C(*,B(*,A))

当n=4时,有336种

当n=5时,有5040种



分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP