从祖先矩阵构造树
给定一个祖先矩阵 mat[n][n],其中祖先矩阵定义如下。
mat[i][j] = 1 if i is ancestor of j
mat[i][j] = 0, otherwise
从给定的祖先矩阵构造一棵二叉树,其中所有节点的值都从 0 到 n-1。
- 可以假设提供程序的输入是有效的,并且可以从中构造树。
- 许多二叉树可以从一个输入构建。该程序将构建其中任何一个。
例子:
Input: 0 1 1
0 0 0
0 0 0
Output: Root of one of the below trees.
0 0
/ \ OR / \
1 2 2 1
Input: 0 0 0 0 0 0
1 0 0 0 1 0
0 0 0 1 0 0
0 0 0 0 0 0
0 0 0 0 0 0
1 1 1 1 1 0
Output: Root of one of the below trees.
5 5 5
/ \ / \ / \
1 2 OR 2 1 OR 1 2 OR ....
/ \ / / / \ / \ /
0 4 3 3 0 4 4 0 3
There are different possible outputs because ancestor
matrix doesn't store that which child is left and which
is right.
我们强烈建议您最小化您的浏览器并首先自己尝试。
解决方案中使用的观察结果:
- 与叶子对应的行全为 0
- 对应于根的行的最大数量为 1。
- 第 i 行中 1 的计数表示节点 i 的后代数。
这个想法是以自下而上的方式构建树。
- 创建一个节点指针数组 node[]。
- 存储与给定计数对应的行号。为此,我们使用了 multimap。
- 处理 multimap 的所有条目从最小计数到最大计数(注意 map 和 multimap 中的条目可以按排序顺序遍历)。对每个条目进行以下操作。
- 为当前行号创建一个新节点。
- 如果该节点不是叶节点,则考虑它的所有未设置父节点的后代,将当前节点作为其父节点。
- 最后处理的节点(具有最大和的节点)是树的根。
下面是上述方法的实现:
C++
// Given an ancestor matrix for binary tree, construct
// the tree.
#include
using namespace std;
# define N 6
/* A binary tree node */
struct Node
{
int data;
Node *left, *right;
};
/* Helper function to create a new node */
Node* newNode(int data)
{
Node* node = new Node;
node->data = data;
node->left = node->right = NULL;
return (node);
}
// Constructs tree from ancestor matrix
Node* ancestorTree(int mat[][N])
{
// Binary array to determine whether
// parent is set for node i or not
int parent[N] = {0};
// Root will store the root of the constructed tree
Node* root = NULL;
// Create a multimap, sum is used as key and row
// numbers are used as values
multimap mm;
for (int i = 0; i < N; i++)
{
int sum = 0; // Initialize sum of this row
for (int j = 0; j < N; j++)
sum += mat[i][j];
// insert(sum, i) pairs into the multimap
mm.insert(pair(sum, i));
}
// node[i] will store node for i in constructed tree
Node* node[N];
// Traverse all entries of multimap. Note that values
// are accessed in increasing order of sum
for (auto it = mm.begin(); it != mm.end(); ++it)
{
// create a new node for every value
node[it->second] = newNode(it->second);
// To store last processed node. This node will be
// root after loop terminates
root = node[it->second];
// if non-leaf node
if (it->first != 0)
{
// traverse row 'it->second' in the matrix
for (int i = 0; i < N; i++)
{
// if parent is not set and ancestor exits
if (!parent[i] && mat[it->second][i])
{
// check for unoccupied left/right node
// and set parent of node i
if (!node[it->second]->left)
node[it->second]->left = node[i];
else
node[it->second]->right = node[i];
parent[i] = 1;
}
}
}
}
return root;
}
/* Given a binary tree, print its nodes in inorder */
void printInorder(Node* node)
{
if (node == NULL)
return;
printInorder(node->left);
printf("%d ", node->data);
printInorder(node->right);
}
// Driver code
int main()
{
int mat[N][N] = {{ 0, 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 1, 0 },
{ 0, 0, 0, 1, 0, 0 },
{ 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 1, 1, 0 }
};
Node* root = ancestorTree(mat);
cout << "Inorder traversal of tree is \n";
// Function call
printInorder(root);
return 0;
}
Java
// Given an ancestor matrix for binary tree, construct
// the tree.
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
/* A binary tree node */
class Node {
int data;
Node left, right;
Node(int d)
{
data = d;
left = right = null;
}
}
public class TreeFromAncestorMatrix {
static Node ancestorNode(int[][] mat)
{
int n = mat.length;
// Binary array to determine whether parent is set
// for node i or not
int[] parent = new int[n];
Node root = null;
// Map to store row numbers as key and
// their sum as their values
Map map = new HashMap<>();
for (int i = 0; i < n; i++) {
int sum = 0;
for (int j = 0; j < n; j++)
sum += mat[i][j];
map.put(i, sum);
}
// node[i] will store node for i in
//constructed tree
Node node[] = new Node[n];
// Sorting the map according to its
//values
Map sorted
= map.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue())
.collect(Collectors.toMap(
e
-> e.getKey(),
e
-> e.getValue(),
(e1, e2) -> e2, LinkedHashMap::new));
// Traverse all entries of sorted Map.
// Note that values are accessed in increasing order
// of sum
for (Map.Entry entry :
sorted.entrySet()) {
int key = entry.getKey();
int value = entry.getValue();
// create a new node for every
// value
node[key] = new Node(key);
// if its is an internal node
if (value != 0) {
// Traverse row
//corresponding to the node
for (int i = 0; i < n; i++)
{
// if parent is not set and
//ancestor exits
if (parent[i] == 0
&& mat[key][i] != 0)
{
// check for unoccupied
// left/right node and
//set parent of node i
if (node[key].left == null)
node[key].left = node[i];
else
node[key].right = node[i];
parent[i] = 1;
}
// To store last processed
// node. This node will be root after
// loop terminates
root = node[key];
}
}
}
return root;
}
/* Given a binary tree, print its nodes in inorder */
static void inOrder(Node root)
{
if (root == null)
return;
inOrder(root.left);
System.out.print(root.data + " ");
inOrder(root.right);
}
// Driver code
public static void main(String[] args)
{
int mat[][] = {
{ 0, 0, 0, 0, 0, 0 }, { 1, 0, 0, 0, 1, 0 },
{ 0, 0, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0 }, { 1, 1, 1, 1, 1, 0 }
};
Node root = ancestorNode(mat);
// Function call
inOrder(root);
}
}
// contribute by amarsomani
Python3
# key structure to store a binary tree node
class Node:
def __init__(self, key, left = None, right = None):
self.key = key
self.left = left
self.right = right
# Utility function to print binary tree nodes in-order fashion
def inorder(node):
if node:
inorder(node.left)
print(node.key, end = ' ')
inorder(node.right)
# Function to construct a binary tree
# from specified ancestor matrix
def constructBT(mat):
# get number of rows in the matrix
N = len(mat)
# create an empty multi-dict
dict = {}
# Use sum as key and row numbers as values in the multi-dict
for i in range(N):
# find the sum of the current row
total = sum(mat[i])
# insert the sum and row number into the dict
dict.setdefault(total, []).append(i)
# node[i] will store node for i in constructed tree
node = [Node(-1)] * N
last = 0
# the value of parent[i] is true if parent is set for i'th node
parent = [False] * N
# Traverse the dictionary in sorted order (default behavior)
for key in dict.keys():
for row in dict.get(key):
last = row
# create a new node
node[row] = Node(row)
# if leaf node, do nothing
if key == 0:
continue
# traverse row
for i in range(N):
# do if parent is not set and ancestor exits
if not parent[i] and mat[row][i] == 1:
# check for the unoccupied node
if node[row].left is None:
node[row].left = node[i]
else:
node[row].right = node[i]
# set parent for i'th node
parent[i] = True
# last processed node is the root
return node[last]
# Construct a Binary Tree from Ancestor Matrix
if __name__ == '__main__':
mat = [[0, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 1, 0],
[0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 0, 0]]
root = constructBT(mat)
inorder(root)
# This code is contributed by Priyadarshini Kumari
C#
// Given an ancestor matrix for binary tree, construct
// the tree.
using System;
using System.Collections.Generic;
using System.Linq;
/* A binary tree node */
public
class Node
{
public
int data;
public
Node left, right;
public
Node(int d)
{
data = d;
left = right = null;
}
}
public class TreeFromAncestorMatrix
{
static Node ancestorNode(int[,] mat)
{
int n = mat.GetLength(0);
// Binary array to determine whether parent is set
// for node i or not
int[] parent = new int[n];
Node root = null;
// Map to store row numbers as key and
// their sum as their values
Dictionary map = new Dictionary();
for (int i = 0; i < n; i++)
{
int sum = 0;
for (int j = 0; j < n; j++)
sum += mat[i, j];
map.Add(i, sum);
}
// node[i] will store node for i in
//constructed tree
Node []node = new Node[n];
var sorted = from entry in map orderby entry.Value ascending select entry;
// Traverse all entries of sorted Map.
// Note that values are accessed in increasing order
// of sum
foreach (KeyValuePair entry in
sorted)
{
int key = entry.Key;
int value = entry.Value;
// create a new node for every
// value
node[key] = new Node(key);
// if its is an internal node
if (value != 0)
{
// Traverse row
//corresponding to the node
for (int i = 0; i < n; i++)
{
// if parent is not set and
//ancestor exits
if (parent[i] == 0
&& mat[key,i] != 0)
{
// check for unoccupied
// left/right node and
//set parent of node i
if (node[key].left == null)
node[key].left = node[i];
else
node[key].right = node[i];
parent[i] = 1;
}
// To store last processed
// node. This node will be root after
// loop terminates
root = node[key];
}
}
}
return root;
}
/* Given a binary tree, print its nodes in inorder */
static void inOrder(Node root)
{
if (root == null)
return;
inOrder(root.left);
Console.Write(root.data + " ");
inOrder(root.right);
}
// Driver code
public static void Main(String[] args)
{
int [,]mat = {
{ 0, 0, 0, 0, 0, 0 }, { 1, 0, 0, 0, 1, 0 },
{ 0, 0, 0, 1, 0, 0 }, { 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0 }, { 1, 1, 1, 1, 1, 0 }
};
Node root = ancestorNode(mat);
// Function call
inOrder(root);
}
}
// This code is contributed by Rajput-Ji
Javascript
输出
0 1 4 5 3 2
请注意,我们还可以使用向量数组来代替 multimap。为简单起见,我们使用了多图。向量数组将提高性能,因为插入和访问元素将花费 O(1) 时间。