#include <stdio.h>
#include <stdlib.h>

// Define the structure for a tree node.
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
};

// Function to create a new tree node.
struct TreeNode* createNode(int value) {
    struct TreeNode* newNode = (struct TreeNode*)malloc(sizeof(struct TreeNode));
    newNode->val = value;
    newNode->left = NULL;
    newNode->right = NULL;
    return newNode;
}

// Function to check if two trees are mirrors of each other.
int areMirrors(struct TreeNode* tree1, struct TreeNode* tree2) {
    // If both nodes are NULL, they are mirrors.
    if (tree1 == NULL && tree2 == NULL) return 1;
    
    // If one of them is NULL, they are not mirrors.
    if (tree1 == NULL || tree2 == NULL) return 0;
    
    // Check if the values of the nodes are equal and if the left subtree of one tree
    // is a mirror of the right subtree of the other tree and vice versa.
    return (tree1->val == tree2->val) &&
           areMirrors(tree1->left, tree2->right) &&
           areMirrors(tree1->right, tree2->left);
}

// Function to check if a tree is symmetric.
int isSymmetric(struct TreeNode* root) {
    // An empty tree is symmetric.
    if (root == NULL) return 1;
    
    // Check if the left and right subtrees are mirrors.
    return areMirrors(root->left, root->right);
}

// Main function to test the code.
int main() {
    // Create a symmetric tree.
    struct TreeNode* root = createNode(1);
    root->left = createNode(2);
    root->right = createNode(2);
    root->left->left = createNode(3);
    root->left->right = createNode(4);
    root->right->left = createNode(4);
    root->right->right = createNode(3);

    // Check if the tree is symmetric.
    if (isSymmetric(root)) {
        printf("The tree is symmetric.\n");
    } else {
        printf("The tree is not symmetric.\n");
    }

    // Free the allocated memory (optional but good practice).
    free(root->left->left);
    free(root->left->right);
    free(root->right->left);
    free(root->right->right);
    free(root->left);
    free(root->right);
    free(root);

    return 0;
}

Explanation

  1. TreeNode Structure: We define a TreeNode structure that holds a value val and pointers to the left and right children.
  2. createNode Function: This function allocates memory for a new node and initializes it with a given value.
  3. areMirrors Function: This recursive function checks if two trees are mirror images of each other:
    • If both nodes are NULL, return 1 (true).
    • If one is NULL and the other isn’t, return 0 (false).
    • Check if the node values are equal, and the left subtree of one is a mirror of the right subtree of the other.
  4. isSymmetric Function: This function checks if the entire tree is symmetric by calling areMirrors with the left and right children of the root.
  5. Main Function: This creates a simple symmetric tree, checks its symmetry, and prints the result.

Output

When the program runs with the example tree, the output will be:

The tree is symmetric.

If you modify the tree structure in the main function (e.g., remove a node), it will print:

The tree is not symmetric.

Memory Management

In this example, memory is freed for each allocated node at the end. It’s a good practice, though the program will automatically free memory on termination in many cases. However, explicitly freeing memory is important in larger applications to prevent memory leaks.

Leave a Reply

Your email address will not be published. Required fields are marked *

Verified by MonsterInsights