Problem description: tree traversal includes pre-order traversal and post-order traversal. (Note: The pre-order definition refers to the access sequence between the node itself and its sub-nodes, rather than the access sequence between the sub-nodes of a node, that is, the order here refers to the parent-child relationship, not the subrelationship ). The binary tree has a middle-order traversal (specifically, the middle-order traversal of the Binary Search Tree is an ordered sequence ).
Because of the hierarchy, these traversal functions are very intuitive and easy to implement using recursive functions. However, for a given binary tree that requires manual calculation of various sequential traversal results, the recursive functions are not suitable for manual calculation because they are easy to understand from the perspective of Computer Implementation, therefore, I used a virtual path to traverse the vertices to manually provide a binary tree traversal result.
This path enters from the root node, and the tree is surrounded by a week. The exit from the root node is complete. When the path passes through the node's ordinal point, the output/access to the node. For example: the left side is the sample binary tree (this example is from system designer (AdvancedProgramMember) Tutorial (p428, edited by Wang chunsen), the virtual path is provided on the right.
For the preceding example Binary Tree, assume that a pedestrian uses the path on the right to walk around the tree and always tries to rotate in the clockwise direction. The sequence of the traveling nodes is as follows:
1-> 2-> 4-> 7-> 4-> 2-> 5-> 2-> 1-> 3-> 6-> 8-> 6-> 9 -> 6-> 3-> 1;
When a node is rotated, as long as you know the position of the node, you can know whether to access the node in the current traversal order based on this information.
In order to complete the preceding method, we first need to know the location of the pedestrian relative to the node's location. Therefore, we need to define the sequence of the Tree node as follows, that is, for a node of the binary tree, this node is surrounded by a week in the direction of 12 o'clock, and seven key nodes are arranged in turn in this circular path, as shown in:
Note:When a child node returns to its parent node along the pointer, we need to clearly know where we are. Therefore, you must know the connection direction of the child node pointing to the parent node. Therefore, in the above definition, you must also specify the direction (left or right) in which the parent node is located, that is, you need to define the left parent/right parent pointer, this is different from a common tree. The parent node of a common tree is only reflected in the "TOP" of the child node, and there is no direction information relative to the child node!
In this way, we can easily give three sequential traversal results on the draft paper. Now we will adoptCodeImplement the above method and define the node according to the model. It will have a pointer array containing seven elements to describe the key nodes on the path, the red vertices (Index 1, 3, 5) in the graph are called order vertices. They are fixed to null, that is, when the path passes through these special points, is the time to access the node (each order point corresponds to a specific traversal order, which has been marked in the figure ). Other elements are links to other nodes (these nodes are actual pointers to other nodes), such as left and right subnodes and parent nodes. Obviously, only one lparent and rparent of a node is not null. If both are null, It is the root node of a binary tree.
The code is actually simulating the process of traveling along the virtual path. When it goes through a pointer to another node, it enters another node (the structure trunk of the tree goes forward). When it goes through a forward point, access the node. The sample code is as follows:
# Include <stdio. h> # Include <Stdlib. h> # Include <String . H> # Define Pointer_count 7 Enum Pointerindexs {idx_lparent = 0 , Idx_order_pre = 1 , Idx_lchild = 2 , Idx_order_mid = 3 , Idx_rchild = 4 , Idx_order_post = 5 , Idx_rparent = 6 ,}; Typedef Struct Tagnode { Int Val; Struct Tagnode * P [pointer_count];} node, * Pnode; // Access Node Void Visit (pnode ){ If (Pnode! = Null) _ tprintf (_ T ( " % LD " ), Pnode-> Val );} // When you enter another node from one node, the orientation inside the node needs to be updated. Int Updateindex ( Int Index ){ // Perform 180-degree flip first Int Newindex = (index> = 4 )? (Index- 4 ): (Index + 4 ); // Move one cell forward immediately Return (Newindex + 1 ) % Pointer_count ;} Void Travel (pnode proot, Int Order ){ Int Index = Idx_lparent, I; // Number of sequential points on the Root Node Int Rootvisittimes = 0 ; Pnode = Proot; While ( 1 ){ // Enter from a certain position, traverse all pointers, and return to the Starting Point For (I = 0 ; I <pointer_count; I ++ ){ If (Pnode-> P [Index]! = Null ){ // Enter next node Pnode = pnode-> P [Index]; // Update Index Index = Updateindex (INDEX ); Break ;} Else { If (Index =Order) visit (pnode ); // If the index is 1, 3, 5, it indicates that the index is an output order point. // If all three vertices of the root node have been accessed, the tree traversal is completed. If (Pnode = proot & (index & 1 )){ ++ Rootvisittimes; If (Rootvisittimes = 3 ) Return ;} Index = (Index + 1 ) % Pointer_count ;}}} // Insert a subnode to a node Pnode insertchild (pnode pparent, Int Ichild, Int Val ){ // The subnode must be null before insertion! Otherwise overwriting will cause memory leakage! If (Pparent! = NULL & pparent-> P [ichild]! =Null) Return NULL; pnode pchild = (Pnode) malloc ( Sizeof (Node); memset (pchild, 0 , Sizeof (Node )); If (Pparent! = Null) pparent -> P [ichild] = Pchild; pchild -> Val = Val; If (Ichild =Idx_lchild) pchild -> P [idx_rparent] = Pparent; Else Pchild -> P [idx_lparent] = Pparent; Return Pchild ;} // Create a binary tree instance demo Pnode builddemotree () {pnode pnode1 = Insertchild (null, idx_lchild, 1 ); Pnode pnode2 = Insertchild (pnode1, idx_lchild, 2 ); Pnode pnode3 = Insertchild (pnode1, idx_rchild, 3 ); Pnode pnode4 = Insertchild (pnode2, idx_lchild, 4 ); Pnode pnode5 = Insertchild (pnode2, idx_rchild, 5 ); Pnode pnode6 = Insertchild (pnode3, idx_rchild, 6 ); Pnode pnode7 = Insertchild (pnode4, idx_lchild, 7 ); Pnode pnode8 = Insertchild (pnode6, idx_lchild,8 ); Pnode pnode9 = Insertchild (pnode6, idx_rchild, 9 ); Return Pnode1 ;} // Releases the memory occupied by binary trees. Void Freetree (pnode proot ){ If (Proot! = Null) {freetree (proot -> P [idx_lchild]); freetree (proot ->P [idx_rchild]); free (proot );}} Int _ Tmain ( Int Argc, _ tchar * Argv []) { Int I; tchar * Names [] = {_ T ( " Pre " ), _ T ( " Mid " ), _ T ( " Post " )}; Int Orders [] = {Idx_order_pre, idx_order_mid, idx_order_post}; pnode proot = Builddemotree (); For (I = 0 ; I < 3 ; I ++ ) {_ Tprintf (_ T ( " Travel % s order: " ), Names [I]); travel (proot, orders [I]); printf ( " \ N " );} // Releases the memory occupied by binary trees. Freetree (proot); proot = NULL; getchar (); Return 0 ;}
In the sample code, the sample Binary Tree in Figure 1 is constructed and traversed respectively in the forward, middle, and backward orders. Visit is an access node function. Currently, it only prints the node value. The output of this program is as follows:
Travel pre order: 1 2 4 7 5 3 6 8 9 Travel mid order: 7 4 2 5 1 3 8 6 9 Travel post order: 7 4 5 2 8 9 6 3 1
Summary:
The advantage is that the parent node of the node and the directionality of the parent node relative to it are described when the tree is built, in this way, we can implement a relatively simple form of a single traversal function (travel), to complete all three methods of traversing a binary tree, you only need to specify the order point in the parameter. This traversal function is not a recursive function (so it does not stack a large number of stack frames as a recursive function), and the Code is easy to read, tree traversal is like traversing a Linear Linked List.
The disadvantage is that each node of this method will contain 7 pointers (higher than the memory occupied by common Binary Tree descriptions), and more than half of them are null pointers. For example, there are too many Fruit Tree nodes, memory needs to be balanced and optimized. For the tree structure, because the memory demand of the complete tree is too fast about the growth speed of the tree depth, for example, the size of the fruit tree is large, you must carefully consider the restrictions of memory demand. In other words, you should only try to build small-scale trees in the memory.
References:
Wang chunsen, system designer (Senior Programmer) tutorial, Tsinghua University Press.
[Supplemental notes]
Many years ago, little Yu xuemei (littlehead) asked me how to use the stack to rewrite the tree traversal problem. At that time, I had not learned any relevant knowledge, therefore, my own ideas may be impractical (but I don't know what the idea was originally given, probably adding a class of identifiers on the tree node), and I didn't provide any implementation. I am sorry that my limited capabilities and knowledge have not actually helped me. After many years, I came up with this idea and implemented my method using code. The method described in this article is also implemented by adding information to the Tree node. In terms of space usage, the state is actually transferred from the auxiliary stack to the node data, therefore, it is an optional method, but not an improvement method.This document is used by Xiaoyu (littlehead) xuemei.