Traversal of Binary Trees and Common Algorithms

Definition of traversal: Access all nodes in ...
Definition of traversal:
Traversal ideas:
Three traversal orders:
Traversal application

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

22 May 2020, 23:34 | Views: 7458

Add new comment

For adding a comment, please log in
or create account

0 comments