您将获得两棵平衡的二进制搜索树,例如AVL或Red Black Tree。编写一个函数,将两个给定的平衡BST合并为一个平衡的二进制搜索树。假设第一棵树中有m个元素,另一棵树中有n个元素。您的合并函数应花费O(m + n)时间。
在以下解决方案中,假定树的大小也作为输入给出。如果未指定大小,则可以通过遍历树来获得大小(请参见此内容)。
方法1(将第一棵树的元素插入第二棵树)
逐个获取第一个BST的所有元素,然后将它们插入第二个BST。将元素插入自平衡BST需要花费Logn时间(请参阅此信息),其中n是BST的大小。因此,此方法的时间复杂度为Log(n)+ Log(n + 1)…Log(m + n-1)。该表达式的值将在mLogn和mLog(m + n-1)之间。作为优化,我们可以选择较小的树作为第一棵树。
方法2(合并有序遍历)
1)对第一棵树进行有序遍历,并将遍历存储在一个临时数组arr1 []中。此步骤需要O(m)时间。
2)对第二棵树进行有序遍历,并将遍历存储在另一个临时数组arr2 []中。此步骤需要O(n)时间。
3)在步骤1和2中创建的数组是有序数组。将两个已排序的数组合并为一个大小为m + n的数组。此步骤需要O(m + n)时间。
4)使用本文讨论的技术从合并数组构造平衡树。此步骤需要O(m + n)时间。
此方法的时间复杂度为O(m + n),比方法1更好。即使输入的BST不平衡,该方法也需要O(m + n)的时间。
以下是此方法的实现。
C++
// C++ program to Merge Two Balanced Binary Search Trees
#include
using namespace std;
/* A binary tree node has data, pointer to left child
and a pointer to right child */
class node
{
public:
int data;
node* left;
node* right;
};
// A utility unction to merge two sorted arrays into one
int *merge(int arr1[], int arr2[], int m, int n);
// A helper function that stores inorder
// traversal of a tree in inorder array
void storeInorder(node* node, int inorder[],
int *index_ptr);
/* A function that constructs Balanced
Binary Search Tree from a sorted array
See https://www.geeksforgeeks.org/sorted-array-to-balanced-bst/ */
node* sortedArrayToBST(int arr[], int start, int end);
/* This function merges two balanced
BSTs with roots as root1 and root2.
m and n are the sizes of the trees respectively */
node* mergeTrees(node *root1, node *root2, int m, int n)
{
// Store inorder traversal of
// first tree in an array arr1[]
int *arr1 = new int[m];
int i = 0;
storeInorder(root1, arr1, &i);
// Store inorder traversal of second
// tree in another array arr2[]
int *arr2 = new int[n];
int j = 0;
storeInorder(root2, arr2, &j);
// Merge the two sorted array into one
int *mergedArr = merge(arr1, arr2, m, n);
// Construct a tree from the merged
// array and return root of the tree
return sortedArrayToBST (mergedArr, 0, m + n - 1);
}
/* Helper function that allocates
a new node with the given data and
NULL left and right pointers. */
node* newNode(int data)
{
node* Node = new node();
Node->data = data;
Node->left = NULL;
Node->right = NULL;
return(Node);
}
// A utility function to print inorder
// traversal of a given binary tree
void printInorder(node* node)
{
if (node == NULL)
return;
/* first recur on left child */
printInorder(node->left);
cout << node->data << " ";
/* now recur on right child */
printInorder(node->right);
}
// A utility unction to merge
// two sorted arrays into one
int *merge(int arr1[], int arr2[], int m, int n)
{
// mergedArr[] is going to contain result
int *mergedArr = new int[m + n];
int i = 0, j = 0, k = 0;
// Traverse through both arrays
while (i < m && j < n)
{
// Pick the smaler element and put it in mergedArr
if (arr1[i] < arr2[j])
{
mergedArr[k] = arr1[i];
i++;
}
else
{
mergedArr[k] = arr2[j];
j++;
}
k++;
}
// If there are more elements in first array
while (i < m)
{
mergedArr[k] = arr1[i];
i++; k++;
}
// If there are more elements in second array
while (j < n)
{
mergedArr[k] = arr2[j];
j++; k++;
}
return mergedArr;
}
// A helper function that stores inorder
// traversal of a tree rooted with node
void storeInorder(node* node, int inorder[], int *index_ptr)
{
if (node == NULL)
return;
/* first recur on left child */
storeInorder(node->left, inorder, index_ptr);
inorder[*index_ptr] = node->data;
(*index_ptr)++; // increase index for next entry
/* now recur on right child */
storeInorder(node->right, inorder, index_ptr);
}
/* A function that constructs Balanced
// Binary Search Tree from a sorted array
See https://www.geeksforgeeks.org/sorted-array-to-balanced-bst/ */
node* sortedArrayToBST(int arr[], int start, int end)
{
/* Base Case */
if (start > end)
return NULL;
/* Get the middle element and make it root */
int mid = (start + end)/2;
node *root = newNode(arr[mid]);
/* Recursively construct the left subtree and make it
left child of root */
root->left = sortedArrayToBST(arr, start, mid-1);
/* Recursively construct the right subtree and make it
right child of root */
root->right = sortedArrayToBST(arr, mid+1, end);
return root;
}
/* Driver code*/
int main()
{
/* Create following tree as first balanced BST
100
/ \
50 300
/ \
20 70
*/
node *root1 = newNode(100);
root1->left = newNode(50);
root1->right = newNode(300);
root1->left->left = newNode(20);
root1->left->right = newNode(70);
/* Create following tree as second balanced BST
80
/ \
40 120
*/
node *root2 = newNode(80);
root2->left = newNode(40);
root2->right = newNode(120);
node *mergedTree = mergeTrees(root1, root2, 5, 3);
cout << "Following is Inorder traversal of the merged tree \n";
printInorder(mergedTree);
return 0;
}
// This code is contributed by rathbhupendra
C
// C program to Merge Two Balanced Binary Search Trees
#include
#include
/* A binary tree node has data, pointer to left child
and a pointer to right child */
struct node
{
int data;
struct node* left;
struct node* right;
};
// A utility unction to merge two sorted arrays into one
int *merge(int arr1[], int arr2[], int m, int n);
// A helper function that stores inorder traversal of a tree in inorder array
void storeInorder(struct node* node, int inorder[], int *index_ptr);
/* A function that constructs Balanced Binary Search Tree from a sorted array
See https://www.geeksforgeeks.org/sorted-array-to-balanced-bst/ */
struct node* sortedArrayToBST(int arr[], int start, int end);
/* This function merges two balanced BSTs with roots as root1 and root2.
m and n are the sizes of the trees respectively */
struct node* mergeTrees(struct node *root1, struct node *root2, int m, int n)
{
// Store inorder traversal of first tree in an array arr1[]
int *arr1 = new int[m];
int i = 0;
storeInorder(root1, arr1, &i);
// Store inorder traversal of second tree in another array arr2[]
int *arr2 = new int[n];
int j = 0;
storeInorder(root2, arr2, &j);
// Merge the two sorted array into one
int *mergedArr = merge(arr1, arr2, m, n);
// Construct a tree from the merged array and return root of the tree
return sortedArrayToBST (mergedArr, 0, m+n-1);
}
/* 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);
}
// A utility function to print inorder traversal of a given binary tree
void printInorder(struct node* node)
{
if (node == NULL)
return;
/* first recur on left child */
printInorder(node->left);
printf("%d ", node->data);
/* now recur on right child */
printInorder(node->right);
}
// A utility unction to merge two sorted arrays into one
int *merge(int arr1[], int arr2[], int m, int n)
{
// mergedArr[] is going to contain result
int *mergedArr = new int[m + n];
int i = 0, j = 0, k = 0;
// Traverse through both arrays
while (i < m && j < n)
{
// Pick the smaler element and put it in mergedArr
if (arr1[i] < arr2[j])
{
mergedArr[k] = arr1[i];
i++;
}
else
{
mergedArr[k] = arr2[j];
j++;
}
k++;
}
// If there are more elements in first array
while (i < m)
{
mergedArr[k] = arr1[i];
i++; k++;
}
// If there are more elements in second array
while (j < n)
{
mergedArr[k] = arr2[j];
j++; k++;
}
return mergedArr;
}
// A helper function that stores inorder traversal of a tree rooted with node
void storeInorder(struct node* node, int inorder[], int *index_ptr)
{
if (node == NULL)
return;
/* first recur on left child */
storeInorder(node->left, inorder, index_ptr);
inorder[*index_ptr] = node->data;
(*index_ptr)++; // increase index for next entry
/* now recur on right child */
storeInorder(node->right, inorder, index_ptr);
}
/* A function that constructs Balanced Binary Search Tree from a sorted array
See https://www.geeksforgeeks.org/sorted-array-to-balanced-bst/ */
struct node* sortedArrayToBST(int arr[], int start, int end)
{
/* Base Case */
if (start > end)
return NULL;
/* Get the middle element and make it root */
int mid = (start + end)/2;
struct node *root = newNode(arr[mid]);
/* Recursively construct the left subtree and make it
left child of root */
root->left = sortedArrayToBST(arr, start, mid-1);
/* Recursively construct the right subtree and make it
right child of root */
root->right = sortedArrayToBST(arr, mid+1, end);
return root;
}
/* Driver program to test above functions*/
int main()
{
/* Create following tree as first balanced BST
100
/ \
50 300
/ \
20 70
*/
struct node *root1 = newNode(100);
root1->left = newNode(50);
root1->right = newNode(300);
root1->left->left = newNode(20);
root1->left->right = newNode(70);
/* Create following tree as second balanced BST
80
/ \
40 120
*/
struct node *root2 = newNode(80);
root2->left = newNode(40);
root2->right = newNode(120);
struct node *mergedTree = mergeTrees(root1, root2, 5, 3);
printf ("Following is Inorder traversal of the merged tree \n");
printInorder(mergedTree);
getchar();
return 0;
}
Java
// Java program to Merge Two Balanced Binary Search Trees
import java.io.*;
import java.util.ArrayList;
// A binary tree node
class Node {
int data;
Node left, right;
Node(int d) {
data = d;
left = right = null;
}
}
class BinarySearchTree
{
// Root of BST
Node root;
// Constructor
BinarySearchTree() {
root = null;
}
// Inorder traversal of the tree
void inorder()
{
inorderUtil(this.root);
}
// Utility function for inorder traversal of the tree
void inorderUtil(Node node)
{
if(node==null)
return;
inorderUtil(node.left);
System.out.print(node.data + " ");
inorderUtil(node.right);
}
// A Utility Method that stores inorder traversal of a tree
public ArrayList storeInorderUtil(Node node, ArrayList list)
{
if(node == null)
return list;
//recur on the left child
storeInorderUtil(node.left, list);
// Adds data to the list
list.add(node.data);
//recur on the right child
storeInorderUtil(node.right, list);
return list;
}
// Method that stores inorder traversal of a tree
ArrayList storeInorder(Node node)
{
ArrayList list1 = new ArrayList<>();
ArrayList list2 = storeInorderUtil(node,list1);
return list2;
}
// Method that merges two ArrayLists into one.
ArrayList merge(ArrayListlist1, ArrayListlist2, int m, int n)
{
// list3 will contain the merge of list1 and list2
ArrayList list3 = new ArrayList<>();
int i=0;
int j=0;
//Traversing through both ArrayLists
while( ilist, int start, int end)
{
// Base case
if(start > end)
return null;
// Get the middle element and make it root
int mid = (start+end)/2;
Node node = new Node(list.get(mid));
/* Recursively construct the left subtree and make it
left child of root */
node.left = ALtoBST(list, start, mid-1);
/* Recursively construct the right subtree and make it
right child of root */
node.right = ALtoBST(list, mid+1, end);
return node;
}
// Method that merges two trees into a single one.
Node mergeTrees(Node node1, Node node2)
{
//Stores Inorder of tree1 to list1
ArrayListlist1 = storeInorder(node1);
//Stores Inorder of tree2 to list2
ArrayListlist2 = storeInorder(node2);
// Merges both list1 and list2 into list3
ArrayListlist3 = merge(list1, list2, list1.size(), list2.size());
//Eventually converts the merged list into resultant BST
Node node = ALtoBST(list3, 0, list3.size()-1);
return node;
}
// Driver function
public static void main (String[] args)
{
/* Creating following tree as First balanced BST
100
/ \
50 300
/ \
20 70
*/
BinarySearchTree tree1 = new BinarySearchTree();
tree1.root = new Node(100);
tree1.root.left = new Node(50);
tree1.root.right = new Node(300);
tree1.root.left.left = new Node(20);
tree1.root.left.right = new Node(70);
/* Creating following tree as second balanced BST
80
/ \
40 120
*/
BinarySearchTree tree2 = new BinarySearchTree();
tree2.root = new Node(80);
tree2.root.left = new Node(40);
tree2.root.right = new Node(120);
BinarySearchTree tree = new BinarySearchTree();
tree.root = tree.mergeTrees(tree1.root, tree2.root);
System.out.println("The Inorder traversal of the merged BST is: ");
tree.inorder();
}
}
// This code has been contributed by Kamal Rawal
Python3
# A binary tree node has data, pointer to left child
# and a pointer to right child
class Node:
def __init__(self, val):
self.val = val
self.left = None
self.right = None
# A utility unction to merge two sorted arrays into one
# Time Complexity of below function: O(m + n)
# Space Complexity of below function: O(m + n)
def merge_sorted_arr(arr1, arr2):
arr = []
i = j = 0
while i < len(arr1) and j < len(arr2):
if arr1[i] <= arr2[j]:
arr.append(arr1[i])
i += 1
else:
arr.append(arr2[j])
j += 1
while i < len(arr1):
arr.append(arr1[i])
i += 1
while i < len(arr2):
arr.append(arr2[j])
j += 1
return arr
# A helper function that stores inorder
# traversal of a tree in arr
def inorder(root, arr = []):
if root:
inorder(root.left, arr)
arr.append(root.val)
inorder(root.right, arr)
# A utility function to insert the values
# in the individual Tree
def insert(root, val):
if not root:
return Node(val)
if root.val == val:
return root
elif root.val > val:
root.left = insert(root.left, val)
else:
root.right = insert(root.right, val)
return root
# Converts the merged array to a balanced BST
# Explanation of the below code:
# https://www.geeksforgeeks.org/sorted-array-to-balanced-bst/
def arr_to_bst(arr):
if not arr:
return None
mid = len(arr) // 2
root = Node(arr[mid])
root.left = arr_to_bst(arr[:mid])
root.right = arr_to_bst(arr[mid + 1:])
return root
if __name__=='__main__':
root1 = root2 = None
# Inserting values in first tree
root1 = insert(root1, 100)
root1 = insert(root1, 50)
root1 = insert(root1, 300)
root1 = insert(root1, 20)
root1 = insert(root1, 70)
# Inserting values in second tree
root2 = insert(root2, 80)
root2 = insert(root2, 40)
root2 = insert(root2, 120)
arr1 = []
inorder(root1, arr1)
arr2 = []
inorder(root2, arr2)
arr = merge_sorted_arr(arr1, arr2)
root = arr_to_bst(arr)
res = []
inorder(root, res)
print('Following is Inorder traversal of the merged tree')
for i in res:
print(i, end = ' ')
# This code is contributed by Flarow4
C#
// C# program to Merge Two Balanced Binary Search Trees
using System;
using System.Collections.Generic;
// 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 BinarySearchTree
{
// Root of BST
public Node root;
// Constructor
public BinarySearchTree()
{
root = null;
}
// Inorder traversal of the tree
public virtual void inorder()
{
inorderUtil(this.root);
}
// Utility function for inorder traversal of the tree
public virtual void inorderUtil(Node node)
{
if (node == null)
{
return;
}
inorderUtil(node.left);
Console.Write(node.data + " ");
inorderUtil(node.right);
}
// A Utility Method that stores inorder traversal of a tree
public virtual List storeInorderUtil(Node node, List list)
{
if (node == null)
{
return list;
}
//recur on the left child
storeInorderUtil(node.left, list);
// Adds data to the list
list.Add(node.data);
//recur on the right child
storeInorderUtil(node.right, list);
return list;
}
// Method that stores inorder traversal of a tree
public virtual List storeInorder(Node node)
{
List list1 = new List();
List list2 = storeInorderUtil(node,list1);
return list2;
}
// Method that merges two ArrayLists into one.
public virtual List merge(List list1, List list2, int m, int n)
{
// list3 will contain the merge of list1 and list2
List list3 = new List();
int i = 0;
int j = 0;
//Traversing through both ArrayLists
while (i < m && j < n)
{
// Smaller one goes into list3
if (list1[i] < list2[j])
{
list3.Add(list1[i]);
i++;
}
else
{
list3.Add(list2[j]);
j++;
}
}
// Adds the remaining elements of list1 into list3
while (i < m)
{
list3.Add(list1[i]);
i++;
}
// Adds the remaining elements of list2 into list3
while (j < n)
{
list3.Add(list2[j]);
j++;
}
return list3;
}
// Method that converts an ArrayList to a BST
public virtual Node ALtoBST(List list, int start, int end)
{
// Base case
if (start > end)
{
return null;
}
// Get the middle element and make it root
int mid = (start + end) / 2;
Node node = new Node(list[mid]);
/* Recursively construct the left subtree and make it
left child of root */
node.left = ALtoBST(list, start, mid - 1);
/* Recursively construct the right subtree and make it
right child of root */
node.right = ALtoBST(list, mid + 1, end);
return node;
}
// Method that merges two trees into a single one.
public virtual Node mergeTrees(Node node1, Node node2)
{
//Stores Inorder of tree1 to list1
List list1 = storeInorder(node1);
//Stores Inorder of tree2 to list2
List list2 = storeInorder(node2);
// Merges both list1 and list2 into list3
List list3 = merge(list1, list2, list1.Count, list2.Count);
//Eventually converts the merged list into resultant BST
Node node = ALtoBST(list3, 0, list3.Count - 1);
return node;
}
// Driver function
public static void Main(string[] args)
{
/* Creating following tree as First balanced BST
100
/ \
50 300
/ \
20 70
*/
BinarySearchTree tree1 = new BinarySearchTree();
tree1.root = new Node(100);
tree1.root.left = new Node(50);
tree1.root.right = new Node(300);
tree1.root.left.left = new Node(20);
tree1.root.left.right = new Node(70);
/* Creating following tree as second balanced BST
80
/ \
40 120
*/
BinarySearchTree tree2 = new BinarySearchTree();
tree2.root = new Node(80);
tree2.root.left = new Node(40);
tree2.root.right = new Node(120);
BinarySearchTree tree = new BinarySearchTree();
tree.root = tree.mergeTrees(tree1.root, tree2.root);
Console.WriteLine("The Inorder traversal of the merged BST is: ");
tree.inorder();
}
}
// This code is contributed by Shrikant13
输出:
Following is Inorder traversal of the merged tree
20 40 50 70 80 100 120 300