Binary Tree roaming programming techniques and techniques Summary (II): recursive conversion is non-recursive

Source: Internet
Author: User
The previous article explains how to compile a recursive program with a binary tree structure. Although the method and strategy of recursive Binary Tree solution are very effective, recursive Programs may generate unacceptable system overhead. Therefore, understand the mechanism of recursive Programs, it is very important to convert a recursive program into a non-recursive program. The recursive mechanism is not mysterious. Recursion is actually a special form

The previous article explains how to compile a recursive program with a binary tree structure. Although the method and strategy of recursive Binary Tree solution are very effective, recursive Programs may generate unacceptable system overhead. Therefore, understand the mechanism of recursive Programs, it is very important to convert a recursive program into a non-recursive program. The recursive mechanism is not mysterious. Recursion is actually a special form

The previous article explains how to compile a recursive program with a binary tree structure. Although the method and strategy of recursive Binary Tree solution are very effective, recursive Programs may generate unacceptable system overhead. Therefore, understand the mechanism of recursive Programs, it is very important to convert a recursive program into a non-recursive program.

The recursive mechanism is not mysterious. Recursion is actually a special form of normal function call, but the called function is exactly the same as the called function, which is a bit difficult for beginners. For recursive Programs, the most important thing is to save the localvariable set and the return address (returnaddress) in the called function and determine the parameter of the function to be called (calledparameters ). When returned from the called function, it can be restored to the status before calling.

Example 1: factorial function

Warm up with the factorial function.

Fac (int n): [1]

If (n = 0) {return 1;} [2]

Else {int local = n; [3]

Inttmp = fac (n-1); [4]

Returnlocal * tmp; [5]

}

This recursive function is relatively simple. The function contains the local variable to be saved. The call parameter is a decreasing integer n. There is only one return exit and the return address is [4]. The user stack contains local variables and return addresses. Although the program is a bit "loose", it is conducive to recursive analysis.

Taking n = 2 as an example, the recursive process is as follows:

Code line

Stack (return address, local variable)

Functions or actions to be called

Return Value

1

Fac (2)

3-4

(4, 2)

Fac (1)

3-4

(4, 2), (4, 1)

Fac (0)

2

(4, 2), (4, 1)

1

4-5

(4, 2)

Back to 4, 1 Output Stack

1*1

4-5

Returns 4 to 2 output stacks.

2*1*1

After analysis, we can obtain:. if n> 0, n is imported into the stack and N-1 is passed into fac () until the input parameter is 0; B. if n = 0, 1; C. is returned. obtain the return address and local variable from the stack and multiply the return value to obtain the result.

Int fac (int n)

{

If (n <0) {errorInfo (); exit ;}

While (n> 0) {stack. push (n); n --;}

Int result = 1; // return value when n = 0

While (! Stack. isEmpty ()){

Result * = stack. pop ();

}

Returnresult;

}


Example 2: recursive post-order traversal

PostTravel (root) {[1]

If (root! = Null) {[2]

PostTravel (root-> left); [3]

Pause (); [4]

PostTravel (root-> right); [5]

Pause (); [6]

Visit (root); [7]

Pause (); [8]

} [9]

}

The difficulty of recursive post-order traversal is that there are two possible return egresses. The hidden local variable is root. The basic tree structure: A (B, C) indicates that the root node is A, the left child is B, and the right child is C. The recursion process is as follows:

Code line

Stack (return address, local variable)

Functions or actions to be called

1

PostTravel ();

2 satisfied

A into the stack;

2-3

(4,)

PostTravel (B );

2 satisfied

B into the stack;

2-3

(4, A), (4, B)

PostTravel (NULL) (Left subtree of B)

2 not met

Return from 9; stack is not empty; B is out of stack; return to 4;

4

(4,)

Root = B; B enters the stack

5

(4, A), (6, B)

PostTravel (NULL) (right subtree of B)

2 not met

Return from 9; stack is not empty; B is out of stack; return to 6;

6-8

(4,)

Visit (B);Return from 9;

Stack is not empty. A outputs the stack and returns to 4;

4

Root = A; A inbound Stack

5

(6,)

PostTravel (C)

2 satisfied

C into the stack;

2-3

(6, A), (4, C)

PostTravel (NULL) (Left subtree of C)

2 not met

Return from 9; stack non-empty; C out stack; return to 4;

4

(6,)

Root = C; C

5

(6, A), (6, C)

PostTravel (NULL) (right subtree of C

2 not met

Return from 9; stack non-empty; C out stack; return to 6;

6-8

(6,)

Visit (C);Return from 9;

Stack is not empty. A outputs stack; 6 is returned;

6-8

Visit ();Return from 9. Stack empty; exit.

Although the data flow and control flow tracking shown above are cumbersome, some useful clues can be obtained: 1. when the system uses a layer of recursive call to return data, it first goes out of the stack and extracts the return address to determine the address to be returned and continues to execute; 2. if the stack is empty when the system returns a recursive call from a layer, it indicates that the recursive call has been completed. 3. if there are multiple return addresses, you must take some measures to identify where to return; 4. the node traversal order of the binary tree is as follows: A-B-LeftNull-B-RightNull-B (print)-A-C-LeftNull-C-RightNull-C (print) -A (print); 5. when A node A of A binary tree is accessed, the right subtree of its parent node is always accessed immediately: if the right subtree of the parent node has been accessed (node A is the right subtree of the parent node), the parent node of the stack is immediately released and accessed. If no access is yet made, access the right subtree of the parent node.

The implementation procedure is as follows:

/*** PostOrderTraverseIter: Non-recursive post-sequential traversal of Binary Trees */private List <TreeNode> postOrderTraverseIter (TreeNode root) {TreeNode List <TreeNode> stack = new sequence List <TreeNode> (); list <TreeNode> nodelist = new ArrayList <TreeNode> (); int flag = 0; // identifies whether the right subtree has been accessed; flag = 0 indicates no access; flag = 1 indicates that TreeNode pNode = root has been accessed; TreeNode tmpNode = null; loop1: for (;) {while (pNode! = Null) {// access left subtree stack. push (pNode); pNode = pNode. getLchild (); flag = 0 ;} loop2: for (;) {if (! Stack. isEmpty () {if (flag = 0) // right subtree that has not accessed the root node {pNode = stack. peek (); // retrieve the right subtree of the root node and access its right subtree pNode = pNode. getRchild (); flag = 1; continue loop1;} if (flag = 1) {// you have accessed the right subtree pNode = stack. pop (); nodelist. add (pNode); // access the root node. In fact, the left and right subtree are empty leaf nodes tmpNode = pNode; // After accessing a node, access the right subtree pNode = stack of its parent node immediately. peek (); // obtain the parent node of this node if (pNode! = Null) {// The parent node is not empty (the root node of the entire tree is not traced back) if (tmpNode = pNode. getRchild () {// If the accessed node is the right child of its parent node, directly trace back to its parent node; continue loop2;} else {// otherwise, right subtree pNode = pNode accessing its parent node. getRchild (); continue loop1 ;}}} else // the stack is empty. The recursive call ends and {break loop1 ;}}} return nodelist ;}

Java (A goto-like statement) -- found that occasionally doing "bad" is quite a sense of accomplishment, HOHO ~.

Like a battle, it seems that non-recursive traversal of Binary Trees is still a bit difficult. It doesn't matter. You just need to practice a lot in everything. So far, we will summarize some methods and techniques for converting recursive Programs into non-recursive functions: 1. use some small examples to track the execution of recursive Programs and understand their mechanisms and processes. 2. discover some key clues that may be helpful for solving the problem and terminating the program. 3. write a non-recursive program to simulate the execution of the recursive program; 4. optimize non-recursive Programs to make them more natural and efficient.


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.