从给定的后序遍历中构建一个完整的N-ary树
改进文章
保存文章
喜欢的文章
- 最后更新: 2022年6月3日
给定一个大小为M的数组 arr[],其中包含完整的N-ary树的后序遍历,任务是生成N-ary树并打印其前序遍历。
一棵完整的树是指树的所有层次都被完全填满,除了可能是最后一个层次,但最后一个层次的节点是尽可能的左边。
例子。
**输入:**arr[] = {5, 6, 7, 2, 8, 9, 3, 4, 1}, N = 3
输出。
上述例子的树状结构
**输入:**arr[] = {7, 8, 9, 2, 3, 4, 5, 6, 1}, N = 5
输出。
第二个例子的完整结构
**办法。**解决该问题的方法是基于以下关于完整的N-ary树的事实。
假设完整的N-ary树的任何一棵子树都有一个高度H。
前H层的节点总数为N0+N1+N2+ ... ...+NH-1=(NH- 1)/(N - 1)。
最后一级的最大可能节点是NH。
因此,如果子树的最后一层至少有NH个节点,那么子树最后一层的总节点是(NH- 1)/(N - 1) +NH高度H可以计算为ceil[logN( M*(N-1) +1)] - 1,因为
N-ary完整二叉树,最多可以有**(NH+1**- 1)/(N - 1)] 个节点。
由于给定的数组包含后序遍历,数组的最后一个元素将总是根节点。现在基于上述观察,剩余的数组可以被划分为该节点的若干个子树。
按照下面提到的步骤来解决这个问题。
- 数组的最后一个元素是树的根。
- 现在把剩下的数组分成子数组,这些子数组代表每个子树的节点总数。
- 每个子树的高度肯定是H-2,根据上述观察,如果任何子树有超过**(NH-1 -1)/(N - 1)个节点,那么它的高度是H-1**。
- 要计算子树的节点数,请遵循以下案例。
- 如果最后一级有超过NH-1的节点,那么这个子树的所有级别都是满的,子树有**(NH-1-1)/(N-1)+NH-1的**节点。
- 否则,该子树将有**(NH-1**-1)/(N-1)+L个节点,其中L是最后一级的节点数。
- L可以计算为L = M - (NH- 1)/(N - 1)。
- 为了生成每个子阵列,重复应用第2到第4步,对每个子树的大小(M)和高度(H)进行相应调整。
- 返回以这种方式形成的树的预排序遍历
为了更好地理解,请看下面的插图
插图。
考虑这个例子:arr[] = {5, 6, 7, 2, 8, 9, 3, 4, 1},N = 3。
所以高度(H)= ceil[log3(9*2+1)] - 1 = ceil[log319] - 1 = 3 - 1 = 2,L = 9 - (32- 1)/2 = 5。
**第1步。**所以根=1
形成树的第1步
**第2步。**剩余的数组将被分解成子树。对于第一个子树H=2。
5>32-1,即L>3。所以最后一层完全被填满,第一个子树的节点数=(3-1)/2+3=4[用上面的公式计算]。第一个子树包含的元素={5,6,7,2}。剩下的部分是{8,9,3,4}
,子树的根=2。现在,当用同样的方法计算5、6、7的子树时,它们没有任何子节点,本身就是叶节点。
生成树的第二步
**第3步。**现在L被更新为2。
2 < 3。所以使用上述公式,第二个子树的节点数为1 + 2 = 3。所以第二棵子树的元素是{8, 9, 3},剩下的部分是{4},3是第二棵子树的根。
生成树的第3步
**第四步。**现在L=0,子树的唯一元素是{4}本身。
树的最终结构
这一步之后,树就完全建成了。
下面是上述方法的实现。
C++
// C++ code to implement the aproach#include <bits/stdc++.h>using namespace std;// Node Classtemplate <typename T>class Node {public:Node(T data);// Get the first child of the NodeNode* get_first_child()const;// Get the Next Sibling of The nodeNode* get_next_sibling()const;// Sets the next sibling of the nodevoid set_next_sibling(Node* node);// Sets the next child of the nodevoid set_next_child(Node* node);// Returns the data the node containsT get_data();private:T data;// We use the first child/next sibling representation// to represent the TreeNode* first_child;Node* next_sibling;};// Using template for generic usagetemplate <typename T> Node<T>::Node(T data){first_child = NULL;next_sibling = NULL;this->data = data;}// Function to get the first childtemplate <typename T>Node<T>* Node<T>::get_first_child()const{return first_child;}// Function to get the siblingstemplate <typename T>Node<T>* Node<T>::get_next_sibling()const{return next_sibling;}// Function to set next siblingtemplate <typename T>void Node<T>::set_next_sibling(Node<T>* node){if (next_sibling == NULL) {next_sibling = node;}else {next_sibling->set_next_sibling(node);}}// Function to get the datatemplate <typename T> T Node<T>::get_data() {return data; }// Function to set the child node valuetemplate <typename T>void Node<T>::set_next_child(Node<T>* node){if (first_child == NULL) {first_child = node;}else {first_child->set_next_sibling(node);}}// Function to construct the treetemplate <typename T>Node<T>* Construct(T* post_order_arr,int size,int k){Node<T>* Root =new Node<T>(post_order_arr[size - 1]);if (size == 1) {return Root;}int height_of_tree=ceil(log2(size * (k - 1) + 1) / log2(k)) - 1;int nodes_in_last_level= size - ((pow(k, height_of_tree) - 1) / (k - 1));int tracker = 0;while (tracker != (size - 1)) {int last_level_nodes= (pow(k, height_of_tree - 1)> nodes_in_last_level)? nodes_in_last_level: (pow(k, height_of_tree - 1));int nodes_in_next_subtree= ((pow(k, height_of_tree - 1) - 1) / (k - 1))+ last_level_nodes;Root->set_next_child(Construct(post_order_arr + tracker,nodes_in_next_subtree, k));tracker = tracker + nodes_in_next_subtree;nodes_in_last_level= nodes_in_last_level - last_level_nodes;}return Root;}// Function to print the preorder traversaltemplate <typename T>void preorder(Node<T>* Root){if (Root == NULL) {return;}cout << Root->get_data() <<" ";preorder(Root->get_first_child());preorder(Root->get_next_sibling());}// Driver codeint main(){int M = 9, N = 3;int arr[] = { 5, 6, 7, 2, 8, 9, 3, 4, 1 };// Function callpreorder(Construct(arr, M, N));return 0;} |
输出
1 2 5 6 7 3 8 9 4
**时间复杂度。**O(M)
**辅助空间。**O(M)用于构建树
我的个人笔记arrow_drop_up
保存