Implementation of Binary Tree Algorithms

Source: Internet
Author: User

Implementation of Binary Tree Algorithms
Preface: Binary Tree is a simple data structure. Understanding and mastering related algorithms is of great benefit to Learning complex data structures. to create a binary tree [do not like the theory I skip>] the so-called Binary Tree creation is actually to allow computers to store this special data structure (where is it special? Especially when it is customized) First, the computer's internal storage is linear, and our tree structure is hierarchical, which is obviously incomprehensible to the computer, the raw data types that the computer can accept cannot meet our needs. Therefore, we have to customize a Data Structure to indicate that the hierarchical relationship is actually to define the structure + operation, the structure is for the operation service. For example, we want to simulate the process of buying tickets. The existing data structure cannot meet our needs (do not mention arrays ...), the required operations may be: 1. obtain the person standing at the top of the ticket buying team. 3. force the person who bought the ticket out of the team. after the first person buys the ticket, all the people behind him must "consciously" move forward to clarify the three operations, and then define the structure based on the operations, finally, we get the binary tree of the queue (array/linked list + corresponding function). What the computer sees is structure + operation. The structure is the Node set (Binary linked list ), the operation is to create, traverse, search, and other function nodes: struct bt {char data; struct bt * left; struct bt * right; }; The node is a bucket with two hands (data is loaded in the bucket, and the two hands reach out and hold the left and right two children): // createBT (); // printBT (); // deleteNode (Node node );//... ------- the above is the understanding of the binary tree, the following is the specific implementation of the creation of the Binary Tree ------- the creation process of the binary tree is actually the traversal process (here refer to the recursive method ), we know that any Traversal method of a binary tree can normalize the tree structure (simply put, a group of traversal results can uniquely represent a binary tree ), therefore, we can use the traversal results to restore a binary tree to traverse the recursive tree in sequence: 1. read the data of the current root node. if it is a space, the current root is left blank; otherwise, a new node is applied for and data is saved. recursive calling using the left and Right pointers of the current root node may not be easy to understand when creating left and right subtree. The Code is as follows: struct bt {char data; struct bt * left; struct bt * right;}; void CreateBT (struct bt ** root) {char c; c = getchar (); if (c = '') * root = NULL; // if it is blank, else {* root = (struct bt *) malloc (sizeof (struct bt) is left blank; // apply for a new node (* root)-> data = c; // Save the data createBT (& (* root)-> left); // create the left subtree of the current node createBT (& (* root)-> right )); // create the right subtree of the current node}. For example, if we want to create a binary tree a (B, c ), you only need to input the first order traversal result AB ××c ×× (× indicates space). The other two build methods are similar and will not be detailed, for non-recursive build methods, see the following non-recursive traversal. traversal traversal can be implemented in recursive and non-recursive modes. The so-called non-recursion is actually converted from recursion (manual maintenance of a stack), with overhead (Memory/time) may be more non-recursive. After all, more information is maintained in the operating system stack, the overhead of on-site storage and recovery should be larger. There are three ways to traverse the order: 1. first traverse (root-left-right) 2. traverse in the middle order (left-root-Right) 3. for example, the three traversal results of Binary Tree a (B, c (d, e) are: 1. abcde 2. badce 3. bdeca ------- let's take a look at recursive and non-recursive implementations of post-sequential traversal. The rest are similar to ------- post-sequential traversal recursion: void postOrder (struct bt * root) {if (root = NULL) return; else {postOrder (root-> left); postOrder (root-> right); putchar (root-> data) ;}} post-order traversal non-recursive: void postOrder (struct st * root) {struct st * Stack [100]; // declare the node stack int top =-1; // stack top index struct bt * p = root; // current node (present) struct bt * q = NULL; // The last processed node while (p! = NULL | top! =-1) {for (; p! = NULL; p = p-> left) stack [++ top] = p; // traverse the left subtree if (top! =-1) {p = stack [top]; if (p-> right = NULL | p-> right = q) // No right child, or the right child has traversed {putchar (p-> data); // The output root node q = p; p = stack [top]; top --; p = NULL ;} else p = p-> right; // traverse the right subtree }}} to make the description clearer, the stack operation is directly implemented above. Of course, A more standardized approach is to encapsulate the stack as an independent data structure and call the operation functions provided by the stack to perform related operations in our functions. A series of operations on the output leaf node to search for a specific node are based on traversal. The output leaf node is an example. If the leaf node meets the condition that the Left and Right children are empty, we only need to add such judgment conditions to the traversal. // here, void printLeaves (struct bt * root) {if (root = NULL) return is first traversed; else {if (root -> Left = NULL & root-> right = NULL) putchar (root-> data); else {printLeaves (root-> left ); printLeaves (root-> right) ;}} are similar operations such as: output nodes that meet certain conditions in the binary tree, delete the specified node, add a node (subtree) at a specified position )... perform some additional operations on the basis of traversal. the deep computing tree of a computing tree has multiple methods, such as: 1. calculate the height of the left and right subtree under the root respectively. The larger of the two is the depth of the tree. the maximum recursive depth is tree depth... we adopt the first method to make it clearer that int btDepth (struct bt * root) {int rd, ld; if (root = NULL) return 0; // The depth of the empty tree is 0 else {ld = 1 + btDepth (root-> left); // recursion into the layer, depth plus 1 rd = 1 + btDepth (roo T-> right); // recursive layer, adding 1 return ld> rd? Ld: rd; // returns the maximum value. tree output refers to the so-called tree output, that is, rotating the Binary Tree represented by nature 90 degrees counter-clockwise. In fact, the recursive layers are recorded during the traversal process to determine the output result. // depth indicates the recursive depth, the initial value is 0 void btOutput (struct bt * root, int depth) {int k; if (root = NULL) return; else {btOutput (root-> right, depth + 1); // traverse the right subtree for (k = 0; k <depth; k ++) printf (""); // Number of recursive layers, output a few spaces (indented) putchar (root-> data); printf ("\ n"); btOutput (root-> left, depth + 1 ); // traverse the left subtree} // The traversal order of "right-middle-left" is called "inverse middle-order" traversal. This order is used to conform to the output rule (90 degrees counter-clockwise) 6. layer-by-layer indent output The layer-by-layer indent output is like the automatic indent in the code editor. It is indented layer by layer starting from the root node. You only need to make slight changes to the above Code to achieve this. // k still indicates the recursive depth, the initial value is 0 void indOutput (struct bt * root, int k) {int I; if (root! = NULL) {for (I = 1; I <= k; I ++) putchar (''); putchar (root-> data ); putchar ('\ n'); indOutput (root-> left, k + 1); indOutput (root-> right, k + 1);} else return ;} // The only difference between layer-by-layer indent output and tree-based output is that the Traversal method is different. The former is sequential traversal, and the latter is inverse central order traversal. the layer-based ordered output is similar to the two output modes mentioned above. In fact, the output is very different, at least, we cannot simply apply any traversal process to accomplish this goal. Therefore, we can only maintain one queue to control the traversal sequence void layerPrint (struct bt * root) {struct bt * queue [100]; // declare the node queue struct bt * p; // the current node int amount = 0, head, tail, j, k; // queue-related attributes (total elements Number, front and back-end indexes) queue [0] = root; head = 0; tail = 1; amount ++; while (1) {j = 0; for (k = 0; k <amount; k ++) {p = queue [head ++]; // obtain the first element if (p-> left! = NULL) {queue [tail ++] = p-> left; // if yes, the left child j ++ is recorded;} if (p-> right! = NULL) {queue [tail ++] = p-> right; // If yes, records the right child j ++;} putchar (p-> data ); // output current node value} amount = j; // update the counter if (amount = 0) break;} 8. to calculate the path from the root node to the specified node, We must record the path. Of course, we should not use a recursive method. Here we use the non-recursive method of post-sequential traversal. Why do we choose post-sequential traversal? In this Traversal method, the existing nodes in the stack at a certain time point are exactly the path from the root node to the current node (from the bottom of the stack to the top of the stack ). Strictly speaking, the queue should be used to store the path at this time, because the stack does not support the operation from the bottom of the stack to the top of the stack (such a small detail will ignore it ...) // parameter c is the specified node value void printPath (struct bt * root, char c) {struct st * stack [100]; // declare the node stack int top =-1; // stack top index int I; struct bt * p = root; // the current node struct bt * q = NULL; // The last processed node while (p! = NULL | top! =-1) {for (; p! = NULL; p = p-> left) stack [++ top] = p; // traverse the left subtree if (top! =-1) {p = stack [top]; // obtain the top element of the stack if (p-> right = NULL | p-> right = q) // if the current node does not have the right child or the right child has just been accessed {if (p-> data = c) // if found, the output path {for (I = 0; I <= top; I ++) {p = stack [I]; putchar (p-> data);} printf ("\ n "); // do not jump out of the loop here, because there may be different node values, traverse the entire tree and find all paths} q = p; p = stack [top]; top --; p = NULL;} else p = p-> right; // traverse the right subtree} 9. complete source code and sample source code: # include <stdio. h> struct bt {char data; struct bt * left; struct bt * right;}; void createBT (struct bt ** Root) {char c; c = getchar (); if (c = '') * root = NULL; else {* root = (struct bt *) malloc (sizeof (struct bt); (* root)-> data = c; createBT (& (* root)-> left )); createBT (& (* root)-> right) ;}} void preOrder (struct bt * root) {if (root = NULL) return; else {putchar (root-> data); preOrder (root-> left); preOrder (root-> right) ;}} void inOrder (struct bt * root) {if (root = NULL) return; else {inOrder (root-> left ); Putchar (root-> data); inOrder (root-> right) ;}} void printLeaves (struct bt * root) {if (root = NULL) return; else {if (root-> left = NULL & root-> right = NULL) putchar (root-> data); else {printLeaves (root-> left ); printLeaves (root-> right) ;}} int btDepth (struct bt * root) {int rd, ld; if (root = NULL) return 0; else {ld = 1 + btDepth (root-> left); rd = 1 + btDepth (root-> right); return ld> rd? Ld: rd ;}} void btOutput (struct bt * root, int depth) {int k; if (root = NULL) return; else {btOutput (root-> right, depth + 1); for (k = 0; k <depth; k ++) printf (""); putchar (root-> data ); printf ("\ n"); btOutput (root-> left, depth + 1) ;}} void postOrder (struct st * root) {struct st * stack [100]; int top =-1; struct bt * p = root; struct bt * q = NULL; while (p! = NULL | top! =-1) {for (; p! = NULL; p = p-> left) stack [++ top] = p; if (top! =-1) {p = stack [top]; if (p-> right = NULL | p-> right = q) {putchar (p-> data ); q = p; p = stack [top]; top --; p = NULL;} else p = p-> right ;}} void printPath (struct bt * root, char c) {struct st * stack [100]; int top =-1; int I; struct bt * p = root; struct bt * q = NULL; while (p! = NULL | top! =-1) {for (; p! = NULL; p = p-> left) stack [++ top] = p; if (top! =-1) {p = stack [top]; if (p-> right = NULL | p-> right = q) {if (p-> data = c) {for (I = 0; I <= top; I ++) {p = stack [I]; putchar (p-> data);} printf ("\ n");} q = p; p = stack [top]; top --; p = NULL ;} else p = p-> right ;}} void layerPrint (struct bt * root) {struct bt * queue [100]; struct bt * p; int amount = 0, head, tail, j, k; queue [0] = root; head = 0; tail = 1; amount ++; while (1) {j = 0; for (k = 0; k <amount; k ++) {p = queue [head ++]; if (p -> Left! = NULL) {queue [tail ++] = p-> left; j ++;} if (p-> right! = NULL) {queue [tail ++] = p-> right; j ++;} putchar (p-> data);} amount = j; if (amount = 0) break;} void indOutput (struct bt * root, int k) {int I; if (root! = NULL) {for (I = 1; I <= k; I ++) putchar (''); putchar (root-> data ); putchar ('\ n'); indOutput (root-> left, k + 1); indOutput (root-> right, k + 1);} else return ;} void main () {char c; struct bt * root; printf ("Please input the first traversal result:"); createBT (& root ); printf ("preOrder traversal (preOrder) [recursion]: \ n"); preOrder (root); printf ("\ n inOrder traversal (inOrder) [recursion]: \ n "); inOrder (root); printf (" \ n post-order traversal (postOrder) [non-recursive]: \ n "); postOrder (root ); printf ("\ n leaf node (leaves): \ n"); printLeaves (root); printf ("\ n depth (depth): \ n "); printf ("% d \ n", btDepth (root); printf ("tree output): \ n"); btOutput (root, 0 ); printf ("indentation output): \ n"); indOutput (root, 0); printf ("Enter the target node ):"); getchar (); c = getchar (); printf ("path): \ n"); printPath (root, c); printf ("layer-by-layer output (layerPrint ): \ n "); layerPrint (root); printf (" \ n ");}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.