Traversal of Binary Trees and Common Algorithms

Definition of traversal:

Access all nodes in a binary tree in some order, and each node is visited only once;

The importance of traversal:

When we need to operate on a binary tree, such as inserting, deleting, searching, etc., we usually need to traverse the binary tree first, which means traversing is the basic operation of the binary tree.

Traversal ideas:

  • The data structure of a binary tree is a recursive definition (each node may contain children of the same structure), so traversal can also use recursion, that is, if the node is not empty, it continues to be called recursively

  • Each node has three fields, data and, left child pointer and right child pointer, each iteration only needs to read data, recursive left subtree, recursive right subtree, these three operations

Three traversal orders:

Depending on the order in which the three domains are accessed, there can be many different traversal orders, and generally the subtrees are accessed in left-to-right order.

Set L to traverse the left subtree, D to access the root node, R to traverse the right subtree, and L must be in front of R

Three different traversal orders can be derived:

Preorder traversal

The order of operation is DLR, first accessing the root node, then traversing the left subtree of the root, and finally traversing the right subtree of the root. Follow these three steps for each subtree (root first, left, then right)

Intermediate traversal

The order of operation is LDR, which first traverses the left subtree of the root, then visits the root node, and finally traverses the right subtree of the root, following these three steps for each subtree (first left, then root, then right)

Post-order traversal

The order of operation is LRD, which first traverses the left subtree of the root, then the right subtree of the root, and finally accesses the root node, so that each subtree is also traversed in these three steps (left, right, and last root).

level traversal

Hierarchical traversal is to traverse all nodes in order from top to bottom, from left to right. To achieve hierarchical traversal, a queue is usually needed to join the next traversed nodes in the queue in turn.

Traversal application

Traversal is the basis for various operations on binary trees, and it allows various operations on nodes during traversal, such as for a known binary tree

  • Finding the Number of Nodes in a Binary Tree
  • Find the number of leaf nodes in a binary tree.
  • Finding the Number of Moderately 1 Nodes in a Binary Tree
  • Finding the Number of Nodes with a Binary Tree Medium of 2
  • 5 Find the number of non-terminal nodes in a binary tree
  • Exchange Node Left and Right Children
  • Determining the hierarchy of nodes

Wait...

C language implementation:

#include <stdio.h>

//Binary Chain List Data Structure Definition
typedef struct TNode {
    char data;
    struct TNode *lchild;
    struct TNode *rchild;
} *BinTree, BinNode;


//Initialization
//Pass in a pointer to point the pointer to NULL
void initiate(BinTree *tree) {
    *tree = NULL;
}

//Create Tree
void create(BinTree *BT) {
    printf("Enter the current node value: (0 Then create an empty node)\n");
    char data;
    scanf(" %c", &data);//Character variables accept line breaks, so spaces are added
    if (data == 48) {
        *BT = NULL;
        return;
    } else {
        //Create Root Node
        //Note that the size of the open space is the size of the structure, not the size of the structure pointer. Writing incorrectly does not immediately cause problems, but there is a high possibility of memory access abnormalities (tearing....) when subsequent data is stored in it.
        *BT = malloc(sizeof(struct TNode));
        //Data Domain Assignment
        (*BT)->data = data;
        printf("Input Node %c Left child of \n", data);
        create(&((*BT)->lchild));//Recursively create left subtree
        printf("Input Node %c Right child of \n", data);
        create(&((*BT)->rchild));//Recursively create right subtree
    }
}

//Seek Parent Node (Parent Node)
BinNode *Parent(BinTree tree, char x) {
    if (tree == NULL)
        return NULL;
    else if ((tree->lchild != NULL && tree->lchild->data == x) ||
            (tree->rchild != NULL && tree->rchild->data == x))
        return tree;
    else{
        BinNode *node1 = Parent(tree->lchild, x);
        BinNode *node2 = Parent(tree->rchild, x);
        return node1 != NULL ? node1 : node2;
    }

}
//Preorder traversal
void PreOrder(BinTree tree) {
    if (tree) {
        //output data
        printf("%c ", tree->data);
        //If not null, continue to recursively determine the two children of this node in order
        PreOrder(tree->lchild);
        PreOrder(tree->rchild);
    }
}

//Middle Order
void InOrder(BinTree tree) {
    if (tree) {
        InOrder(tree->lchild);
        printf("%c ", tree->data);
        InOrder(tree->rchild);
    }
}

//Postorder
void PostOrder(BinTree tree) {
    if (tree) {
        PostOrder(tree->lchild);
        PostOrder(tree->rchild);
        printf("%c ", tree->data);
    }
}


//Destroy Nodes Recursively free All Nodes
void DestroyTree(BinTree *tree) {
    if (*tree != NULL) {
        printf("free %c \n", (*tree)->data);
        if ((*tree)->lchild) {
            DestroyTree(&((*tree)->lchild));
        }
        if ((*tree)->rchild) {
            DestroyTree(&((*tree)->rchild));
        }
        free(*tree);
        *tree = NULL;
    }
}

// Finding nodes with X elements uses hierarchical traversal
BinNode *FindNode(BinTree tree, char x) {
    if (tree == NULL) {
        return NULL;
    }
    //queue
    BinNode *nodes[1000] = {};
    //Queue head and tail position
    int front = 0, real = 0;
    //Insert the root node at the end of the queue
    nodes[real] = tree;
    real += 1;
    //Continue if queue is not empty
    while (front != real) {
        //Remove Queue Head Node Output Data
        BinNode *current = nodes[front];
        if (current->data == x) {
            return current;
        }
        front++;
        //Queue a node if it has children (left/right) at the current node
        if (current->lchild != NULL) {
            nodes[real] = current->lchild;
            real++;
        }
        if (current->rchild != NULL) {
            nodes[real] = current->rchild;
            real++;
        }
    }
    return NULL;
}

//level traversal
// Finding nodes with X elements uses hierarchical traversal
void LevelOrder(BinTree tree) {
    if (tree == NULL) {
        return;
    }
    //queue
    BinNode *nodes[1000] = {};
    //Queue head and tail position
    int front = 0, real = 0;
    //Insert the root node at the end of the queue
    nodes[real] = tree;
    real += 1;
    //Continue if queue is not empty
    while (front != real) {
        //Remove Queue Head Node Output Data
        BinNode *current = nodes[front];
        printf("%2c", current->data);
        front++;
        //Queue a node if it has children (left/right) at the current node
        if (current->lchild != NULL) {
            nodes[real] = current->lchild;
            real++;
        }
        if (current->rchild != NULL) {
            nodes[real] = current->rchild;
            real++;
        }
    }
}


//Find the left child of x
BinNode *Lchild(BinTree tree, char x) {
    BinTree node = FindNode(tree, x);
    if (node != NULL) {
        return node->lchild;
    }
    return NULL;
}

//Find the right child of x
BinNode *Rchild(BinTree tree, char x) {
    BinTree node = FindNode(tree, x);
    if (node != NULL) {
        return node->rchild;
    }
    return NULL;
}


//Finding the Number of Leaf Nodes
int leafCount(BinTree *tree) {
    if (*tree == NULL)
        return 0;
        //If both left and right subtrees are empty, the node is a leaf and subsequent recursion is not required
    else if (!(*tree)->lchild && !(*tree)->rchild)
        return 1;
    else
        //If a subtree exists for the current node, the left and right subtrees are recursively added together
        return leafCount(&((*tree)->lchild)) + leafCount(&((*tree)->rchild));
}


//Finding the Number of Non-leaf Nodes
int NotLeafCount(BinTree *tree) {
    if (*tree == NULL)
        return 0;
        //If both the left and right subtrees of the node are empty, then the leaves do not need to be recursive
    else if (!(*tree)->lchild && !(*tree)->rchild)
        return 0;
    else
        //If the current node has left and right subtrees, it is a non-leaf node (number + 1). The non-leaf nodes in the left and right subtrees are obtained recursively and the results are added together
        return NotLeafCount(&((*tree)->lchild)) + NotLeafCount(&((*tree)->rchild)) + 1;
}

//Find the height (depth) of the tree
int DepthCount(BinTree *tree) {
    if (*tree == NULL)
        return 0;
    else{
        //If the current node is not empty then the depth + 1 is added to the height of the subtree.
        int lc = DepthCount(&((*tree)->lchild)) + 1;
        int rc = DepthCount(&((*tree)->rchild)) + 1;
        return lc > rc?lc:rc;// Maximum depth of two subtrees
    }
}

//Delete left subtree
void RemoveLeft(BinNode *node){
    if (!node)
        return;
    if (node->lchild)
        DestroyTree(&(node->lchild));
    node->lchild = NULL;
}
//Delete Right Subtree
void RemoveRight(BinNode *node){
    if (!node)
        return;
    if (node->rchild)
        DestroyTree(&(node->rchild));
    node->rchild = NULL;
}

int main() {
    BinTree tree;
    create(&tree);
    BinNode *node = Parent(tree, 'G');
    printf("G The parent node of is%c\n",node->data);
    BinNode *node2 = Lchild(tree, 'D');
    printf("D The left child node of%c\n",node2->data);
    BinNode *node3 = Rchild(tree, 'D');
    printf("D The right child node of is%c\n",node3->data);
    printf("Traversal in order is:");
    PreOrder(tree);
    printf("\n");
    printf("Intermediate traversal is:");
    InOrder(tree);
    printf("\n");
    printf("Post-order traversal is:");
    PostOrder(tree);
    printf("\n");
    printf("Hierarchical traversal is:");
    LevelOrder(tree);
    printf("\n");

    int a = leafCount(&tree);
    printf("Number of leaf nodes is%d\n",a);
    int b = NotLeafCount(&tree);
    printf("The number of non-leaf nodes is%d\n",b);
    int c = DepthCount(&tree);
    printf("Depth is%d\n",c);

    //Find F Node
    BinNode *node4 = FindNode(tree,'C');

    RemoveLeft(node4);
    printf("delete C Traverse after the left child of:");
    LevelOrder(tree);
    printf("\n");
    
    RemoveRight(node4);
    printf("delete C Traverse after right child of:");
    LevelOrder(tree);
    printf("\n");
    
    //Destroy Trees
    printf("Destroy Trees \n");
    DestroyTree(&tree);
    printf("Traverse after destruction:");
    LevelOrder(tree);
    printf("\n");
    printf("Hello, World!\n");
    return 0;
}
Test:

The test data is the following binary tree:

Run the program to copy and paste the following:

A
B
D
G
0
0
H
0
0
E
0
0
C
K
0
0
F
I
0
J
0
0
0

Special thanks: iammomo

Tags: C

Posted on Fri, 22 May 2020 23:34:33 -0400 by hach22