Data structure-traversal of two-fork tree

Source: Internet
Author: User

"Tree" is an important data structure, this paper discusses the traversal problem of binary tree, which is described in C language.

One or two Fork Tree Foundation

1) Definition: There is only one root node, root nodes, each junction has only one parent node, a maximum of two child nodes, child nodes have left and right points.
2) Storage structure

Binary tree storage structure can be used in sequential storage, but also can adopt chain storage, in which chain storage more flexible.

In a chained storage structure, like a linear list, each node of a binary tree is represented by a struct, which consists of three fields: a data field, a left pointer, and a right pointer.

The binary tree is defined in the C language such as the following:

struct bitreenode{int c; struct bitreenode *left; struct bitreenode *right;};

Two or two traversal of a fork tree

"Traversal" is the basis for various operations of the two-fork tree. Binary tree is a nonlinear structure, its traversal is not as easy as the linear list, and can not be realized by simple loop.

Binary tree is a kind of tree structure, traversal is to let all the nodes in the tree be and only visited once, that is, according to a certain law arranged into a linear queue. A binary (sub) tree is a recursive defined structure consisting of three parts: the root node (N), the Zuozi (L), and the right subtree (R). The traversal of the two-fork tree is categorized according to the order of the three-part visits, and there are 6 traversal scenarios: NLR, LNR, LRN, NRL, RNL, and LNR. The study of the traversal of the binary tree is to study these 6 detailed traversal schemes, obviously according to the simple symmetry, Saozi right subtree traversal interchangeable, namely NLR and NRL, LNR and RNL, LRN and RLN, respectively, so only need to study NLR, LNR and LRN Three, respectively, called " The first sequence traversal, the middle sequence traversal, and the post-order traversal.

Binary tree traversal usually borrows the data structure such as "stack", there are two ways: recursion and non-recursive way.

In the recursive way, the stack is maintained by the operating system, users do not have to care about the details of the stack operation, the user only need to care about the "Order of Access". Therefore, the recursive way to achieve two-fork tree traversal is easier to understand, the algorithm is simple, easy to achieve.

Recursive implementation of the two-fork-tree traversal of the C language code such as the following:

First order traversal--Recursive int traversebitreepreorder (Bitreenode *ptree,int (*visit) (int)) {if (Ptree) {if (visit (ptree->c)) if ( Traversebitreepreorder (Ptree->left,visit)) if (Traversebitreepreorder (ptree->right,visit)) return 1;  return 0 normally;   Error returned}else return 1;   Normal return}//in sequence traversal--recursive int traversebitreeinorder (bitreenode *ptree,int (int)) {if (*visit) {if ( Traversebitreeinorder (Ptree->left,visit)) if (visit (ptree->c)) if (Traversebitreeinorder (Ptree->right, Visit)) return 1;return 0;} else return 1;} Post-post traversal--recursive int traversebitreepostorder (Bitreenode *ptree,int (*visit) (int)) {if (Ptree) {if (Traversebitreepostorder ( Ptree->left,visit)) if (Traversebitreepostorder (ptree->right,visit)) if (visit (ptree->c)) return 1;return 0;} else return 1;}

In the above code, visit is a function pointer that passes the operation of the node in the binary tree, with the prototype: Int (*visit) (char).

As you know, when the function is called, it will take the initiative to push the stack itself, and when the call returns, it will take the pop of the stack on its own initiative. function recursive call is nothing more than a stack to return the push and pop, since the recursive way to achieve a two-fork tree traversal, then borrow "stack" in a non-recursive way, but also to achieve traversal. However, the stack operation at this time (push, pop, etc.) is carried out by the user, so the implementation will be more complex, and not easy to understand, but it helps us to the tree structure of the traversal has a deep, clear understanding.

Before we discuss the non-recursive traversal, we define the stack and the various stack operations that need to be used:

//stack definition, stack data is "tree node pointer" struct Stack{bitreenode **top; Bitreenode **base;int size;}; #define STACK_INIT_SIZE 100#define stack_inc_size 10//initialize empty stack, pre-allocate storage space stack* Initstack () {Stack *qs=null;qs= (stack *) malloc (Stack); qs->base= (Bitreenode * *) calloc (stack_init_size,sizeof (Bitreenode *));qs->top=qs-> Base;qs->size=stack_init_size;return QS;} Fetch stack Top data bitreenode* getTop (Stack *qs) {Bitreenode *ptree=null;if (qs->top==qs->base) return null;ptree=* (qs-> TOP-1); return ptree;} into the stack operation int push (stack *qs,bitreenode *ptree) {if (qs->top-qs->base>=qs->size) {qs->base= (Bitreenode *) ReAlloc (Qs->base, (qs->size+stack_inc_size) *sizeof (Bitreenode *)); qs->top=qs->base+qs->size;qs- >size+=stack_inc_size;} *qs->top++=ptree;return 1;} Out of stack operation bitreenode* Pop (stack *qs) {if (qs->top==qs->base) return Null;return *--qs->top;} Infer whether the stack is empty int isEmpty (stack *qs) {return qs->top==qs->base;} 

First, non-recursive first-order traversal (NLR) is considered. When traversing a binary (sub) tree, record the two-fork (left-child) tree currently being processed with a current pointer and the right subtree that is processed after the current tree is saved in a stack. First of all, visit the root node of the current tree data, the next should traverse its Saozi right subtree, but the control flow of the program can only handle one, so consider the right subtree root in the stack, the current pointer to the left subtree to be processed first, prepare for the next cycle; If the current pointer to a tree is empty, the current tree is empty tree , do not need to do whatever processing, directly pop up the top of the sub-tree, for the next cycle to prepare. The corresponding C language code is as follows:

First order traversal--Non-recursive int traverseBiTreePreOrder2 (Bitreenode *ptree,int (*visit) (int)) {Stack *qs=null; Bitreenode *pt=null;qs=initstack ();p t=ptree;while (pt | |!isempty (QS)) {if (PT) {if (!visit (pt->c)) return 0;  Error return push (qs,pt->right);p T=pt->left;} else Pt=pop (QS);} return 1;   Normal return}

In contrast to non-recursive first-order traversal, non-recursive middle order/post-sequence traversal is slightly more complicated.

For non-recursive middle order traversal, if the current tree is not empty tree, then visit the root node should first visit its left subtree, so the current root node into the stack, and then consider its left subtree, continue to the non-empty root nodes into the stack, until the left dial hand tree is an empty tree, when the left dial hand tree is empty, do not need to do whatever processing, pop and visit the top node of the stack, Then point to its right subtree and prepare for the next loop.

Middle sequence traversal--non-recursive int traverseBiTreeInOrder2 (Bitreenode *ptree,int (*visit) (int)) {Stack *qs=null; Bitreenode *pt=null;qs=initstack ();p t=ptree;while (pt | |!isempty (QS)) {if (PT) {push (QS,PT);p T=pt->left;} Else{pt=pop (QS); if (!visit (pt->c)) return 0;pt=pt->right;}} return 1;} Middle-order traversal-non-recursive-there is also an implementation of int traverseBiTreeInOrder3 (Bitreenode *ptree,int (*visit) (int)) {Stack *qs=null; Bitreenode *pt=null;qs=initstack ();p Ush (Qs,ptree), while (!isempty (QS)) {while (Pt=gettop (QS)) push (Qs,pt->left); Pt=pop (QS), if (!isempty (QS)) {Pt=pop (QS), if (!visit (pt->c)) return 0;push (Qs,pt->right);}} return 1;}

Finally, the non-recursive sequential traversal is talked about. Because when visiting the root node of the current tree, you should first visit its left, right subtree, so first the root node into the stack, and then the right subtree into the stack, and then consider the left subtree, repeated this process until a left subtree is empty; Assuming that the currently considered subtree is empty, if the top of the stack is not empty, the right subtree of the corresponding tree at the top of the second stack is not processed, The top of the stack pops up, the next loop processing, and a null pointer into the stack to indicate that it has a subtree has been processed; if the top of the stack is also an empty tree, indicating that the tree of the second stack at the top of the left or right subtree is empty, or have been processed, direct access to the top node of the second stack, access to the end point, if the stack is still non-empty, indicating that the whole tree has not been traversed, The top of the stack is popped, and a null pointer to the stack indicates that one of the sub-trees in the top of the second stack has been processed.

Post-post traversal--non-recursive int traverseBiTreePostOrder2 (Bitreenode *ptree,int (*visit) (int)) {Stack *qs=null; Bitreenode *pt=null;qs=initstack ();p t=ptree;while (1)  //Loop condition constant "true" {if (PT) {push (QS,PT);p ush (qs,pt->right);p t =pt->left;} else if (!pt) {Pt=pop (QS), if (!pt) {Pt=pop (QS), if (!visit (pt->c)) return 0;if (IsEmpty (QS)) return 1;pt=pop (QS);} Push (Qs,null);}} return 1;}


Three or two creation of a fork tree

After talking about the traversal of the two-fork tree, we'll talk about the creation of the binary tree, where the creation refers to the input of each node element (character) in the binary tree from the console (first/middle/post order) and the empty tree with a "space".

Because console input is stored in the input buffer, the "order" of the traversal is reflected in the order in which the input characters are read.

The following is a recursive implementation of the first order to create a two-fork tree C code.

Create a two-fork tree-First order input-recursive bitreenode* Createbitreepreorder () {Bitreenode *ptree=null;char Ch;ch=getchar (); if (ch== ") ptree= null;else{ptree= (struct Bitreenode *) malloc (sizeof (Bitreenode));p tree->c=ch;ptree->left= Createbitreepreorder ();p tree->right=createbitreepreorder ();} return ptree;}

For empty trees, functions are returned directly, and for non-empty trees, the characters are read and assigned to the current root node, then the left subtree is created, and the right subtree is created at the end. Therefore, to first know whether the tree currently being created is empty, the ability to do the corresponding processing, "First order" traversal method is very good to meet this point. But the sequence or order is not the same, and more importantly, the sequence or order of the input character sequences can not uniquely determine a binary tree. I have not found in the sequence/post-implementation of the two-tree creation (console input) similar to the simple method, I hope that members of my colleagues to teach ha!

Iv. Implementation and Results

For example, the following two-tree test, first order input to create a two-fork tree, and then call each traversal function.

First Order Input format: ABC ^ ^ D E ^ G ^ ^ F ^ ^ ^ (middle, ^ denotes space character)

The traversal operation uses the Putchar function in the standard I/O library, whose prototype is: int putchar (int);

The results of the various forms of traversal output are:

First Order: ABCDEGF

Middle order: CBEGDFA

Post-post: CGEFDBA

The main functions of the test program are as follows:

int main (int argc, char* argv[]) {Bitreenode *proot=null;printf ("inorder input chars to create a bitree:");p Root=createbit Reepreorder ();  Input (ABC  DE G  F   ) printf ("Preorder Output the Bitree recursively:"); Traversebitreepreorder (Proot,putchar );p rintf ("\ n");p rintf ("Preorder Output the Bitree non-recursively:"); TraverseBiTreePreOrder2 (Proot,putchar);p rintf ("\ n");p rintf ("Inorder Output the Bitree recursively:") Traversebitreeinorder (Proot,putchar);p rintf ("\ n");p rintf (" Inorder Output The Bitree non-recursively (1): "), TraverseBiTreeInOrder2 (Proot,putchar);p rintf (" \ n ");p rintf (" Inorder Output the Bitree non-recursively (2): "), TraverseBiTreeInOrder3 (Proot,putchar);p rintf (" \ n ");p rintf (" Postorder Output the Bitree non-recursively: "), Traversebitreepostorder (Proot,putchar);p rintf (" \ n ");p rintf (" Postorder output The Bitree recursively: "); TraverseBiTreePostOrder2 (Proot,putchar);p rintf (" \ n "); return 0;}

Data structure-traversal of a two-fork tree

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.