将任意二叉树转换为包含 Children Sum 属性的树
问题:给定一棵任意二叉树,将其转换为具有 Children Sum 属性的二叉树。您只能增加任何节点中的数据值(您不能更改树的结构,也不能减少任何节点的值)。
例如,下面的树不包含子 sum 属性,将其转换为包含该属性的树。
50
/ \
/ \
7 2
/ \ /\
/ \ / \
3 5 1 30
算法:
以后序遍历给定的树进行转换,即先改变左右子节点以保持子节点和属性,然后改变父节点。
让节点数据和子节点总和之间的差异为差异。
diff = node’s children sum - node’s data
如果 diff 为 0,则无需执行任何操作。
如果 diff > 0(节点的数据小于节点的子节点总和)将节点的数据增加 diff。
如果 diff < 0(节点的数据大于节点的子节点总和),则增加一个子节点的数据。如果它们都不是NULL,我们可以选择增加左或右孩子。让我们总是首先增加左孩子。增加一个孩子会改变子树的孩子总和属性,所以我们也需要改变左子树。所以我们递归地增加左孩子。如果左孩子为空,那么我们递归地为右孩子调用 increment()。
让我们运行给定示例的算法。
首先转换左子树(增量 7 到 8)。
50
/ \
/ \
8 2
/ \ /\
/ \ / \
3 5 1 30
然后转换右子树(增量2到31)
50
/ \
/ \
8 31
/ \ / \
/ \ / \
3 5 1 30
现在转换根,我们必须增加左子树来转换根。
50
/ \
/ \
19 31
/ \ / \
/ \ / \
14 5 1 30
请注意最后一步——我们将 8 增加到 19,为了修复子树,我们将 3 增加到 14。
执行:
C++
/* C++ Program to convert an arbitrary
binary tree to a tree that hold
children sum property */
#include
using namespace std;
class node
{
public:
int data;
node* left;
node* right;
/* Constructor that allocates a new node
with the given data and NULL left and right
pointers. */
node(int data)
{
this->data = data;
this->left = NULL;
this->right = NULL;
}
};
/* This function is used
to increment left subtree */
void increment(node* node, int diff);
/* This function changes a tree
to hold children sum property */
void convertTree(node* node)
{
int left_data = 0, right_data = 0, diff;
/* If tree is empty or it's a leaf
node then return true */
if (node == NULL || (node->left == NULL &&
node->right == NULL))
return;
else
{
/* convert left and right subtrees */
convertTree(node->left);
convertTree(node->right);
/* If left child is not present then 0 is used
as data of left child */
if (node->left != NULL)
left_data = node->left->data;
/* If right child is not present then 0 is used
as data of right child */
if (node->right != NULL)
right_data = node->right->data;
/* get the diff of node's data and children sum */
diff = left_data + right_data - node->data;
/* If node's children sum is
greater than the node's data */
if (diff > 0)
node->data = node->data + diff;
/* THIS IS TRICKY --> If node's data
is greater than children sum,
then increment subtree by diff */
if (diff < 0)
increment(node, -diff); // -diff is used to make diff positive
}
}
/* This function is used
to increment subtree by diff */
void increment(node* node, int diff)
{
/* IF left child is not
NULL then increment it */
if(node->left != NULL)
{
node->left->data = node->left->data + diff;
// Recursively call to fix
// the descendants of node->left
increment(node->left, diff);
}
else if (node->right != NULL) // Else increment right child
{
node->right->data = node->right->data + diff;
// Recursively call to fix
// the descendants of node->right
increment(node->right, diff);
}
}
/* Given a binary tree,
printInorder() prints out its
inorder traversal*/
void printInorder(node* node)
{
if (node == NULL)
return;
/* first recur on left child */
printInorder(node->left);
/* then print the data of node */
cout<data<<" ";
/* now recur on right child */
printInorder(node->right);
}
/* Driver code */
int main()
{
node *root = new node(50);
root->left = new node(7);
root->right = new node(2);
root->left->left = new node(3);
root->left->right = new node(5);
root->right->left = new node(1);
root->right->right = new node(30);
cout << "\nInorder traversal before conversion: " << endl;
printInorder(root);
convertTree(root);
cout << "\nInorder traversal after conversion: " << endl;
printInorder(root);
return 0;
}
// This code is contributed by rathbhupendra
C
/* Program to convert an arbitrary binary tree to
a tree that holds children sum property */
#include
#include
struct node
{
int data;
struct node* left;
struct node* right;
};
/* This function is used to increment left subtree */
void increment(struct node* node, int diff);
/* Helper function that allocates a new node
with the given data and NULL left and right
pointers. */
struct node* newNode(int data);
/* This function changes a tree to hold children sum
property */
void convertTree(struct node* node)
{
int left_data = 0, right_data = 0, diff;
/* If tree is empty or it's a leaf node then
return true */
if (node == NULL ||
(node->left == NULL && node->right == NULL))
return;
else
{
/* convert left and right subtrees */
convertTree(node->left);
convertTree(node->right);
/* If left child is not present then 0 is used
as data of left child */
if (node->left != NULL)
left_data = node->left->data;
/* If right child is not present then 0 is used
as data of right child */
if (node->right != NULL)
right_data = node->right->data;
/* get the diff of node's data and children sum */
diff = left_data + right_data - node->data;
/* If node's children sum is greater than the node's data */
if (diff > 0)
node->data = node->data + diff;
/* THIS IS TRICKY --> If node's data is greater than children sum,
then increment subtree by diff */
if (diff < 0)
increment(node, -diff); // -diff is used to make diff positive
}
}
/* This function is used to increment subtree by diff */
void increment(struct node* node, int diff)
{
/* IF left child is not NULL then increment it */
if(node->left != NULL)
{
node->left->data = node->left->data + diff;
// Recursively call to fix the descendants of node->left
increment(node->left, diff);
}
else if (node->right != NULL) // Else increment right child
{
node->right->data = node->right->data + diff;
// Recursively call to fix the descendants of node->right
increment(node->right, diff);
}
}
/* Given a binary tree, printInorder() prints out its
inorder traversal*/
void printInorder(struct node* node)
{
if (node == NULL)
return;
/* first recur on left child */
printInorder(node->left);
/* then print the data of node */
printf("%d ", node->data);
/* now recur on right child */
printInorder(node->right);
}
/* Helper function that allocates a new node
with the given data and NULL left and right
pointers. */
struct node* newNode(int data)
{
struct node* node =
(struct node*)malloc(sizeof(struct node));
node->data = data;
node->left = NULL;
node->right = NULL;
return(node);
}
/* Driver program to test above functions */
int main()
{
struct node *root = newNode(50);
root->left = newNode(7);
root->right = newNode(2);
root->left->left = newNode(3);
root->left->right = newNode(5);
root->right->left = newNode(1);
root->right->right = newNode(30);
printf("\n Inorder traversal before conversion ");
printInorder(root);
convertTree(root);
printf("\n Inorder traversal after conversion ");
printInorder(root);
getchar();
return 0;
}
Java
// Java program to convert an arbitrary binary tree to a tree that holds
// children sum property
// A binary tree node
class Node
{
int data;
Node left, right;
Node(int item)
{
data = item;
left = right = null;
}
}
class BinaryTree
{
Node root;
/* This function changes a tree to hold children sum
property */
void convertTree(Node node)
{
int left_data = 0, right_data = 0, diff;
/* If tree is empty or it's a leaf node then
return true */
if (node == null
|| (node.left == null && node.right == null))
return;
else
{
/* convert left and right subtrees */
convertTree(node.left);
convertTree(node.right);
/* If left child is not present then 0 is used
as data of left child */
if (node.left != null)
left_data = node.left.data;
/* If right child is not present then 0 is used
as data of right child */
if (node.right != null)
right_data = node.right.data;
/* get the diff of node's data and children sum */
diff = left_data + right_data - node.data;
/* If node's children sum is greater than the node's data */
if (diff > 0)
node.data = node.data + diff;
/* THIS IS TRICKY --> If node's data is greater than children
sum, then increment subtree by diff */
if (diff < 0)
// -diff is used to make diff positive
increment(node, -diff);
}
}
/* This function is used to increment subtree by diff */
void increment(Node node, int diff)
{
/* IF left child is not NULL then increment it */
if (node.left != null)
{
node.left.data = node.left.data + diff;
// Recursively call to fix the descendants of node->left
increment(node.left, diff);
}
else if (node.right != null) // Else increment right child
{
node.right.data = node.right.data + diff;
// Recursively call to fix the descendants of node->right
increment(node.right, diff);
}
}
/* Given a binary tree, printInorder() prints out its
inorder traversal*/
void printInorder(Node node)
{
if (node == null)
return;
/* first recur on left child */
printInorder(node.left);
/* then print the data of node */
System.out.print(node.data + " ");
/* now recur on right child */
printInorder(node.right);
}
// Driver program to test above functions
public static void main(String args[])
{
BinaryTree tree = new BinaryTree();
tree.root = new Node(50);
tree.root.left = new Node(7);
tree.root.right = new Node(2);
tree.root.left.left = new Node(3);
tree.root.left.right = new Node(5);
tree.root.right.left = new Node(1);
tree.root.right.right = new Node(30);
System.out.println("Inorder traversal before conversion is :");
tree.printInorder(tree.root);
tree.convertTree(tree.root);
System.out.println("");
System.out.println("Inorder traversal after conversion is :");
tree.printInorder(tree.root);
}
}
// This code has been contributed by Mayank Jaiswal(mayank_24)
Python3
# Program to convert an arbitrary binary tree
# to a tree that holds children sum property
# Helper function that allocates a new
# node with the given data and None
# left and right pointers.
class newNode:
# Construct to create a new node
def __init__(self, key):
self.data = key
self.left = None
self.right = None
# This function changes a tree to
# hold children sum property
def convertTree(node):
left_data = 0
right_data = 0
diff=0
# If tree is empty or it's a
# leaf node then return true
if (node == None or (node.left == None and
node.right == None)):
return
else:
""" convert left and right subtrees """
convertTree(node.left)
convertTree(node.right)
""" If left child is not present then 0
is used as data of left child """
if (node.left != None):
left_data = node.left.data
""" If right child is not present then 0
is used as data of right child """
if (node.right != None):
right_data = node.right.data
""" get the diff of node's data
and children sum """
diff = left_data + right_data - node.data
""" If node's children sum is greater
than the node's data """
if (diff > 0):
node.data = node.data + diff
""" THIS IS TRICKY -. If node's data is
greater than children sum, then increment
subtree by diff """
if (diff < 0):
increment(node, -diff) # -diff is used to
# make diff positive
""" This function is used to increment
subtree by diff """
def increment(node, diff):
""" IF left child is not None
then increment it """
if(node.left != None):
node.left.data = node.left.data + diff
# Recursively call to fix the
# descendants of node.left
increment(node.left, diff)
elif(node.right != None): # Else increment right child
node.right.data = node.right.data + diff
# Recursively call to fix the
# descendants of node.right
increment(node.right, diff)
""" Given a binary tree, printInorder()
prints out its inorder traversal"""
def printInorder(node):
if (node == None):
return
""" first recur on left child """
printInorder(node.left)
""" then print the data of node """
print(node.data,end=" ")
""" now recur on right child """
printInorder(node.right)
# Driver Code
if __name__ == '__main__':
root = newNode(50)
root.left = newNode(7)
root.right = newNode(2)
root.left.left = newNode(3)
root.left.right = newNode(5)
root.right.left = newNode(1)
root.right.right = newNode(30)
print("Inorder traversal before conversion")
printInorder(root)
convertTree(root)
print("\nInorder traversal after conversion ")
printInorder(root)
# This code is contributed by
# Shubham Singh(SHUBHAMSINGH10)
C#
// C# program to convert an arbitrary
// binary tree to a tree that holds
// children sum property
using System;
// A binary tree node
public class Node
{
public int data;
public Node left, right;
public Node(int item)
{
data = item;
left = right = null;
}
}
class GFG
{
public Node root;
/* This function changes a tree to
hold children sum property */
public virtual void convertTree(Node node)
{
int left_data = 0, right_data = 0, diff;
/* If tree is empty or it's a leaf
node then return true */
if (node == null || (node.left == null &&
node.right == null))
{
return;
}
else
{
/* convert left and right subtrees */
convertTree(node.left);
convertTree(node.right);
/* If left child is not present then
0 is used as data of left child */
if (node.left != null)
{
left_data = node.left.data;
}
/* If right child is not present then
0 is used as data of right child */
if (node.right != null)
{
right_data = node.right.data;
}
/* get the diff of node's data
and children sum */
diff = left_data + right_data - node.data;
/* If node's children sum is greater
than the node's data */
if (diff > 0)
{
node.data = node.data + diff;
}
/* THIS IS TRICKY --> If node's data is
greater than children sum, then increment
subtree by diff */
if (diff < 0)
{
// -diff is used to make diff positive
increment(node, -diff);
}
}
}
/* This function is used to increment
subtree by diff */
public virtual void increment(Node node, int diff)
{
/* IF left child is not NULL then
increment it */
if (node.left != null)
{
node.left.data = node.left.data + diff;
// Recursively call to fix the
// descendants of node->left
increment(node.left, diff);
}
else if (node.right != null) // Else increment right child
{
node.right.data = node.right.data + diff;
// Recursively call to fix the
// descendants of node->right
increment(node.right, diff);
}
}
/* Given a binary tree, printInorder()
prints out its inorder traversal*/
public virtual void printInorder(Node node)
{
if (node == null)
{
return;
}
/* first recur on left child */
printInorder(node.left);
/* then print the data of node */
Console.Write(node.data + " ");
/* now recur on right child */
printInorder(node.right);
}
// Driver Code
public static void Main(string[] args)
{
GFG tree = new GFG();
tree.root = new Node(50);
tree.root.left = new Node(7);
tree.root.right = new Node(2);
tree.root.left.left = new Node(3);
tree.root.left.right = new Node(5);
tree.root.right.left = new Node(1);
tree.root.right.right = new Node(30);
Console.WriteLine("Inorder traversal " +
"before conversion is :");
tree.printInorder(tree.root);
tree.convertTree(tree.root);
Console.WriteLine("");
Console.WriteLine("Inorder traversal " +
"after conversion is :");
tree.printInorder(tree.root);
}
}
// This code is contributed by Shrikant13
Javascript
输出:
Inorder traversal before conversion is :
3 7 5 50 1 2 30
Inorder traversal after conversion is :
14 19 5 50 1 31 30
时间复杂度: O(n^2),最坏情况下的复杂度是一棵倾斜的树,使得节点从根到叶按降序排列。