statement: Little brother to write a blog soon, mainly to work while learning while writing blog, if wrong, hope you forgive and guidance.
Binary tree is a commonly used nonlinear data structure, and binary tree is composed of two disjoint two-tree trees, a root node and a left and right subtree called the root. The binary tree has some special properties, such as 2^ (i-1) nodes on the first layer. The chain-store structure of the binary tree is as follows:
typedef struct BTNODE{CHAR data; character type data; struct btnode* lchild,*rchild; Pointer to left and right child nodes;} Btnode,*bitree;
Data is stored in a two-fork tree, which stores character data, Lchild and Rchild, respectively, pointing to the left and right child nodes of the nodes in the binary tree. The traversal of the binary tree is the most basic part of the two-fork tree, and the traversal of the binary tree can be divided into the first (root) sequence traversal, the middle (root) sequence traversal and the back (root) traversal according to the order of traversing the root nodes. Before traversing the binary tree, let's look at how to create a two-pronged tree.
1. Create a two-fork tree
You can create a two-fork tree based on a string of characters, creating a binary tree in order sequence:
bitree& Createbitree (Bitree &bitree) { //Enter a string of characters, '? ' is a terminator; Char ch;scanf ("%c", &ch); if (ch== '? ') {Bitree=null;return bitree;} Else{bitree= (btnode*) malloc (sizeof (Btnode));bitree->data=ch; Createbitree (Bitree->lchild); Createbitree (bitree->rchild); return bitree;}}
2, Binary tree traversal
The traversal of a two-fork tree is the most basic operation of a two-fork tree, and the traversal refers to how the algorithm can be used to access the nodes of a two-fork tree. The traversal of binary tree can be divided into recursive way and non-recursive way traversal. First we look at recursive traversal of the binary tree.
PrintOut of/*************************************** node data; **************************************/void Vistor (BTNode* Pnode) {if (pnode==null) {return;} if (Pnode->data!=nullkey) {printf ("%c", Pnode->data);}} /***************************************** recursive traversal of a two-fork tree; ****************************************/void PreOrder ( Bitree root) { //Note the judgment of the critical condition; if (root!=null) {vistor (root); Preorder (Root->lchild); Preorder (Root->rchild);}} The middle sequence traversal recursion of the/***************************************** two fork tree; ****************************************/void InOrder ( Bitree root) {if (root!=null) {inorder (root->lchild); Vistor (root); inorder (Root->rchild);}} /***************************************** two fork tree after the post-traversal recursion; ****************************************/void PostOrder ( Bitree root) {if (root!=null) {postorder (root->lchild); Postorder (Root->rchild); Vistor (root);}}
3. Non-recursive traversal of binary tree
In fact, a recursive algorithm in the execution of the call process, essentially implicitly used a recursive work stack, its role is at different levels of recursive invocation of information protection and recovery. If you explicitly use a stack in the algorithm, you can design a non-recursive algorithm that is easy to understand.
(1) First Order traversal
Idea: Directly first access the node data, and then traverse the left subtree, the left sub-tree node pressure stack, when the left dial hand tree is empty, the top node in the popup stack, and then traverse the right sub-tree.
<span style= "FONT-SIZE:18PX;" >void PreOrder2 (bitree root) { btnode* pnode=root; //define a stack to hold nodes; std::stack<BTNode*> stacknode; while (pnode!=null| |! Stacknode.empty ()) { if (pnode!=null) { //added to the stack; stacknode.push (pnode); // Because it is a pre-order traversal, the direct access to the node; vistor (pnode); //point to left node; pNode=pNode-> lchild; } else { //Stack top node; pnode=stacknode.top (); //stack top pointer minus one; stacknode.pop (); //points to the right node of the top of the stack; pnode=pnode- >rChild; } }}</span>
(2) Middle sequence traversal
Idea: first traverse the left subtree, the left sub-tree node pressure stack, when the left dial hand tree is empty, in the pop-up stack top node, access node data, and then traverse the right subtree.
<span style= "FONT-SIZE:18PX;" >void InOrder2 (bitree root) { btnode* pnode=root; std::stack<BTNode*> stacknode; while (pnode!=null| |! Stacknode.empty ()) { if (pnode!=null) { //The root node directly into the stack due to the first traversal of the left subtree; stacknode.push (pnode); pNode=pNode->lChild; } else { //traverse the root node if the left dial hand tree is empty ; pnode=stacknode.top (); stacknode.pop (); vistor (pnode); //and then traverse right subtree; pNode=pNode->rChild; } }}<span style= "color: #FF6666;" ></span></span><span style= "Font-size:18px;color: #FF6666;" ></span>
(3) post-traversal
Idea: The non-recursive algorithm of the post-order traversal of two fork tree is more complicated than the its first sequence and the non-recursive algorithm of middle order, and the order traversal must be carried out in the sequence of "left-right-root". Therefore, the root node cannot be accessed first, the root pointer must be stored in the stack, and then go through the left subtree of the root. When the left subtree is completed, the root pointer is removed from the stack, and no access to the root pointer is allowed. You must also hold the root pointer in the stack for the second time and then go back to the right subtree of the root. After the right subtree has been traversed, the pointer is removed from the top of the stack again to access the root pointer.
because the root node two times out of the stack, it is necessary to use an identity to distinguish the number of times out of the stack, so you need to change the data structure of the node, add a tag variable to record the number of times out of the stack, when the 2nd time out of the stack to access.
<span style= "FONT-SIZE:18PX;" >typedef struct Btnodepost {bitree bitree; Record tree node; char tag; Record the number of nodes out of the stack;} Btnodepost,*bitreepost;void PostOrder2 (bitree root) {stack<btnodepost*> stacknodepost; btnode* Pnode=root;while (pnode!=null| |! Stacknodepost.empty ()) {if (pnode!=null) {//nodes are not empty, create a new structure, and set the tag value to 1; btnodepost* btnodepost= (btnodepost*) malloc (sizeof (btnodepost)); btnodepost->bitree=pnode;btnodepost->tag=1 ;p Node=pnode->lchild;stacknodepost.push (btnodepost);} else{btnodepost* btnodepost=stacknodepost.top (); Stacknodepost.pop ();//If the tag value is 1, continue adding the stack and set tag to 2;if (btnodepost- >tag==1) {Stacknodepost.push (btnodepost);p node=btnodepost->bitree->rchild;btnodepost->tag=2;} else{//is accessed when the tag value is 2. Vistor (Btnodepost->bitree);p Node=null;}}} </span>
4, the binary tree hierarchy traversal
A hierarchy traversal is a rule that iterates from the root node and accesses the nodes in the tree from left to right, from top to bottom in the hierarchy order. A hierarchy traversal takes a work queue, first putting the root node into the queues, then repeatedly out of the queue, and into row the left and right subtree nodes of the pointer out of the queue until the queue is empty.
void Levelorder (btnode* root) {if (null==root) {return;} Queue<btnode*> Queuenode; btnode* Pnode=root;queuenode.push (Root), while (!queuenode.empty ()) {Pnode=queuenode.front (); Queuenode.pop (); Vistor (Pnode); if (pnode->lchild!=null) {Queuenode.push (pnode->lchild);} if (pnode->rchild!=null) {Queuenode.push (pnode->rchild);}}}
5. Summary
The traversal of the binary tree is summarized here, and the following will continue to learn and summarize some algorithms for binary tree. If the code after testing the test case, if there are details of the problem is not handled, hope to forgive and correct, thank you!
Traversal summary of binary tree of data structure