📜  遍历 N 叉树的方法数

📅  最后修改于: 2022-05-13 01:57:17.072000             🧑  作者: Mango

遍历 N 叉树的方法数

给定一个 n 元树,计算从根顶点开始遍历 n 元(或有向无环图)树的方法数。
假设我们有一个给定的 N 叉树,如下所示。

海军陆战队

现在我们必须找到从根顶点开始遍历整棵树的方法数。可以有很多这样的方式。下面列出了其中一些。
1) N->M->K->J->B->F->D->E->C->H->I->L->A(一种深度优先遍历)。
2) A->B->F->D->E->K->J->G->C->H->I->N->M->L(层序遍历)
3) …………
4) …………
.
.
.
等等…。
我们强烈建议您最小化您的浏览器并首先自己尝试。
所有遍历方式的计数是每个节点的子节点数的阶乘乘积。请参阅下图以清楚地了解-

玛丽纽

这里,
'A' 有四个孩子,所以 4!可能的排列
'B' 有两个孩子,所以 2!可能的排列
'F' 没有孩子,所以 0!可能的排列
……
等等
因此,所有这些方式都是- 4! * 2! * 0! * 1! * 3! * 2! * 0! * 0! * 0! * 0! * 1! * 0! * 0! = 576 路
那是大量的方式,其中只有少数被证明是有用的,比如-inorder,level-order,preorder,postorder(根据这些遍历的流行度排列)

C++
// C++ program to find the number of ways to traverse a
// n-ary tree starting from the root node
#include 
using namespace std;
 
// Structure of a node of an n-ary tree
struct Node
{
   char key;
   vector child;
};
 
// Utility function to create a new tree node
Node *newNode(int key)
{
   Node *temp = new Node;
   temp->key = key;
   return temp;
}
 
// Untility Function to find factorial of given number
int factorial(int n)
{
   if (n == 0)
     return 1;
   return n*factorial(n-1);
}
 
// Function to calculate the number of ways of traversing
// the n-ary starting from root.
// This function is just a modified breadth-first search.
// We can use a depth-first search too.
int calculateWays(Node * root)
{
   int ways = 1;  // Initialize result
 
   // If the tree is empty there is no way of traversing
   // the tree.
   if (root == NULL)
      return 0;
 
   // Create a queue and enqueue root to it.
   queueq;
   q.push(root);
 
   // Level order traversal.
   while (!q.empty())
   {
         // Dequeue an item from queue and print it
         Node * p = q.front();
         q.pop();
 
         // The number of ways is the product of
         // factorials of number of children of each node.
         ways = ways*(factorial(p->child.size()));
 
         // Enqueue all childrent of the dequeued item
         for (int i=0; ichild.size(); i++)
            q.push(p->child[i]);
    }
 
   return(ways);
}
 
// Driver program
int main()
{
   /*   Let us create below tree
   *           A
   *         / /  \  \
   *       B  F   D  E
   *      / \     |  /|\
   *     K  J    G  C H I
   *      /\            \
   *    N   M            L
   */
 
   Node *root = newNode('A');
   (root->child).push_back(newNode('B'));
   (root->child).push_back(newNode('F'));
   (root->child).push_back(newNode('D'));
   (root->child).push_back(newNode('E'));
   (root->child[0]->child).push_back(newNode('K'));
   (root->child[0]->child).push_back(newNode('J'));
   (root->child[2]->child).push_back(newNode('G'));
   (root->child[3]->child).push_back(newNode('C'));
   (root->child[3]->child).push_back(newNode('H'));
   (root->child[3]->child).push_back(newNode('I'));
   (root->child[0]->child[0]->child).push_back(newNode('N'));
   (root->child[0]->child[0]->child).push_back(newNode('M'));
   (root->child[3]->child[2]->child).push_back(newNode('L'));
 
   cout << calculateWays(root); ;
 
   return 0;
}


Javascript


输出:

576

时间复杂度:我们在级别顺序遍历期间访问每个节点一次,并花费 O(n) 时间来计算每个节点的阶乘。总时间为 O(Nn),其中 N = n 叉树中的节点数。我们可以通过计算从 1 到 n 的所有数字的阶乘来优化解决方案以在 O(N) 时间内工作。
辅助空间:由于我们只为每个节点使用一个队列和一个结构,所以整体空间复杂度也是 O(N)。
常见陷阱:由于阶乘的乘积往往会变得非常巨大,因此可能会溢出。最好在 C/C++ 中使用 unsigned long long int 等数据类型,因为路数永远不能是负数。在Java和Python中有 Big Integer 来处理溢出问题。