Tree Isomorphism Problem In C++ - C++ Programming Tutorial
C++ Course / Data Structures / Tree Isomorphism Problem In C++

Tree Isomorphism Problem In C++

BLUF: Mastering Tree Isomorphism Problem In C++ is a critical step in becoming a proficient C++ developer. This lesson provides a deep dive into the syntax, performance considerations, and real-world applications of this concept.
Key Performance Insight: Tree Isomorphism Problem In C++

C++ is renowned for its efficiency. Learn how Tree Isomorphism Problem In C++ enables low-level control and high-performance computing in the tutorial below.

The mystery surrounding tree isomorphism in the field of computer science is intriguing due to its challenge of determining if two specified trees exhibit an isomorphic connection. This involves exploring the possibility of converting one tree into another by interchanging the left and right offspring of specific nodes. Within this article, we will explore the complexities of the tree isomorphism dilemma, highlight its significance, and showcase a C++ code implementation, along with a comprehensive illustration.

What is a Tree Isomorphism?

The issue of tree isomorphism holds a significant position in algorithmic logic, commonly appearing in various areas like data structures, graph theory, and pattern identification. It presents a traditional problem that can be effectively solved using techniques like depth-first search (DFS) or other methods of traversing trees.

In basic language, two trees labeled as T1 and T2 form an isomorphic connection when it's possible to create a one-to-one correspondence between their nodes. This enables a transformation that maintains the structure by swapping left and right children of certain nodes.

C++ Implementation:

Beginning a C++ implementation, we utilize a recursive approach to navigate through the tree structures and confirm their isomorphic characteristics.

Example

// Include directives
#include <iostream>
#include <unordered_map>
#include <vector>
 
// Namespace declaration
using namespace std;
 
// Tree Node Definition
struct TreeNode {
    int data;
    TreeNode* left;
    TreeNode* right;
 
    TreeNode(int val) : data(val), left(nullptr), right(nullptr) {}
};
 
// Function for checking tree isomorphism
bool isIsomorphic(TreeNode* root1, TreeNode* root2) {
    // Base cases
    if (!root1 && !root2)
        return true;
    if (!root1 || !root2)
        return false;
 
    // Verify root node equality
    if (root1->data != root2->data)
        return false;
 
    // Recursively check isomorphism
    return (isIsomorphic(root1->left, root2->left) && isIsomorphic(root1->right, root2->right)) ||
           (isIsomorphic(root1->left, root2->right) && isIsomorphic(root1->right, root2->left));
}
 
// Main function
int main() {
    // Example trees
    TreeNode* tree1 = new TreeNode(1);
    tree1->left = new TreeNode(2);
    tree1->right = new TreeNode(3);
    tree1->left->left = new TreeNode(4);
    tree1->left->right = new TreeNode(5);
 
    TreeNode* tree2 = new TreeNode(1);
    tree2->left = new TreeNode(3);
    tree2->right = new TreeNode(2);
    tree2->right->left = new TreeNode(5);
    tree2->right->right = new TreeNode(4);
 
    // Check isomorphism
    if (isIsomorphic(tree1, tree2))
        cout << "The trees are isomorphic.\n";
    else
        cout << "The trees are not isomorphic.\n";
 
    return 0;
}

Output:

Output

The trees are isomorphic.

Explanation:

  • In this example, we define a TreeNode structure to represent tree nodes.
  • The isIsomorphic function employs recursion to validate if two trees are isomorphic.
  • In the main function, two example trees are created, and the isIsomorphic function determines their isomorphism.

While the earlier C++ code accurately identifies the isomorphism of two trees, there is room for improvement and enhancement. To boost both the efficiency and clarity of the code, we can introduce supplementary data structures. In particular, utilizing a hash table to retain node mappings can reduce unnecessary comparisons.

Example:

Example

#include <iostream>
#include <unordered_map>
#include <vector>
 
using namespace std;
 
// Definition of Tree Node
struct TreeNode {
    int data;
    TreeNode* left;
    TreeNode* right;
 
    TreeNode(int val) : data(val), left(nullptr), right(nullptr) {}
};
 
// Function to ascertain whether two trees are isomorphic
bool isIsomorphic(TreeNode* root1, TreeNode* root2, unordered_map<TreeNode*, TreeNode*>& mapping) {
    // Base cases
    if (!root1 && !root2)
        return true;
    if (!root1 || !root2)
        return false;
 
    // Confirm equality of root node values
    if (root1->data != root2->data)
        return false;
 
    // Check for existing mapping
    if (mapping.find(root1) != mapping.end() && mapping[root1] != root2)
        return false;
 
    // Establish mapping
    mapping[root1] = root2;
 
    // Recursively validate isomorphism
    return (isIsomorphic(root1->left, root2->left, mapping) && isIsomorphic(root1->right, root2->right, mapping)) ||
           (isIsomorphic(root1->left, root2->right, mapping) && isIsomorphic(root1->right, root2->left, mapping));
}
 
int main() {
    // Sample trees
    TreeNode* tree1 = new TreeNode(1);
    tree1->left = new TreeNode(2);
    tree1->right = new TreeNode(3);
    tree1->left->left = new TreeNode(4);
    tree1->left->right = new TreeNode(5);
 
    TreeNode* tree2 = new TreeNode(1);
    tree2->left = new TreeNode(3);
    tree2->right = new TreeNode(2);
    tree2->right->left = new TreeNode(5);
    tree2->right->right = new TreeNode(4);
 
    // Confirm isomorphism of the trees
    unordered_map<TreeNode*, TreeNode*> mapping;
    if (isIsomorphic(tree1, tree2, mapping))
        cout << "The trees are isomorphic.\n";
    else
        cout << "The trees are not isomorphic.\n";
 
    // Memory cleanup
    delete tree1;
    delete tree2;
 
    return 0;
}

Output:

Output

The trees are isomorphic.

Conclusion:

In summary, delving into the tree isomorphism quandary uncovers its complex characteristics and its essential significance in algorithmic logic. Although the initial C++ setup exhibited operationality, it also pinpointed areas for enhancement. The improved iteration incorporated a hash table, boosting effectiveness and clarity by reducing repetitive evaluations. This strategy offers notable benefits for expansive trees, emphasizing performance optimizations. By employing these strategies, we not only confirmed isomorphism but also illustrated the iterative enhancement of resolutions. This process emphasizes the evolving nature of algorithmic conundrums, highlighting the persistent quest for efficiency and sophistication in formulating elegantly structured code.

Input Required

This code uses input(). Please provide values below:

Logic Practice
Install Logic Practice
Add to home screen for a faster app-like experience