Things have outs, there is always, know the order, then a shortcut. -----Preface.
Botwong halfway into the it to do code farming, but also half a year, unexpectedly "uppity" to Shenzhen to break the world. A few hundred resumes, a week after the company invited to interview, in addition to the basic Java grammar and development experience, a larger company will have a few questions for you to do (algorithm problem). Botwong is confused, and the heart is very angry! Gas! Gas! Gas! In the past, he studied "theory and practice of human psychology", and the only computer basis was the use of Word and Excel to quote prices to customers. I have to take the hard way to learn Java grammar and EE framework, such as my case has been outstanding, why should I so harsh, hum! Botwong Since then hated those who like to test the company, and vowed to never go to such a company interview!
Botwong and I are good friends, he put forward his own confusion: in the end to learn these look at "useless" algorithm, ask me how to look at this matter, how to do. Fortunately, Botwang is still a sober-minded person, otherwise he will not ask such a question. I think he is very sincere, he wrote some of his previous code, which contains some algorithms, take it out in general to say again, suggest that he himself to realize it again. Botwang disappeared in March, when the good-bye, has been able to perceive its ability to soar, is not the botwong of March ago. My heart is very comforting, I have written before the collection of the class are posted out, convenient for themselves and the online baby at any time to look at, at any time to replenish energy.
One or two fork tree class:
PackageTree;/*** Binary Tree Data carrier class *@authortery * *@param<T>*/ Public classBinarytreenode<t> { PrivateT data;//Weight valuePrivateBinarytreenode<t>left;//left childPrivateBinarytreenode<t>right;//Right Child PublicBinarytreenode (T data) { This. data=data; Left=right=NULL; } PublicT GetData () {return This. Data; } Public voidsetData (T data) { This. data=data; } PublicBinarytreenode<t>GetLeft () {returnLeft ; } Public voidSetleft (binarytreenode<t>Left ) { This. left =Left ; } PublicBinarytreenode<t>getRight () {returnRight ; } Public voidSetright (binarytreenode<t>Right ) { This. right =Right ; }
/**
* Insert Weight value
*/
@SuppressWarnings ("Unchecked") Publicbinarytreenode<t> Insert (binarytreenode<t>Node,integer data) { if(node==NULL){ return NewBinarytreenode<t>((T) data); }
If the weight of the current node is greater than data, insert it on the left child nodeif(Integer.valueof (Node.getdata (). toString ()) >data) {Node.left=Insert (Node.getleft (), data); }
If the weight of the current node is greater than data, insert it on the left child node
if(Integer.valueof (Node.getdata (). toString ()) <data) {Node.right=Insert (Node.getright (), data);}
// equal throw exception
if (Integer.valueof (Node.getdata (). toString ()) = =data) {
Throw New IllegalArgumentException ("The Data:" +data+ "is already exsist in the tree"
return node;
}
Recursion involved in the Insert method:
0: Aload_11: Ifnonnull - 4:New#1 //class Tree/binarytreenode 7: DUP8: Aload_29: Invokespecial # $ //Method "<init>":(ljava/lang/object;) V A: Areturn -: Aload_1 -: GetField # - //Field Data:ljava/lang/object; at: Aload_2 -: If_icmple - $: GetField # - //Field Left:ltree/binarytreenode; the: Aload_2 +: Invokevirtual # - //Method Insert: (Ltree/binarytreenode; Ljava/lang/object;) Ltree/binarytreenode; +: Putfield # - //Field Left:ltree/binarytreenode; -: Aload_1 the: Areturn
Above is the instructions that the JVM of the Insert method executes, and I excerpt some of the key points to illustrate how recursion is done:
Parameters in the local variable table in the Insert function stack: The first is the current tree node object (temporarily called REF0), the second is a reference to the node object passed in in the function (called REF1), and the third is the constant data passed in (#20 in the constant pool)
0:aload_1 pushes the first reference type local variable to the top of the stack, which is the reference to the Node object in the Insert method (REF1)
1:ifnonnull 13 If REF1 is not empty, jump to 13 rows to execute
4-12: If it is empty, then this node is the node we want to insert, call its constructor <init> method, assign the data value to it, and then Areturn (return the newly generated object reference)
13:aload_1 push Ref1 into the top of the stack
14:getfield the value of the data of the current object ref1 in the constant pool into the top of the stack
23:aload_2 pushes the incoming data value into the top of the stack
30:if_icmple 79, if the incoming data value is less than the ref1 weight, then jump to 79 to execute
36:getfield #24, the constant pool is #24, that is, left pressed into the stack, that is, a reference to the left constant
The 39:aload_2 pushes the data value into the stack. In fact, 36, 392 step instruction is to prepare for the following 40 lines, 40 lines call the Insert method, passed to its required parameters
40:invokevirtrual #53, call the Insert method, and bring the two parameters that are prepared for 36, 39 rows over
43:putfield #24 to assign a value to the left field of the current instance Ref1
79:aload_1, pressing the current instance ref1 into the stack
80:areturn, return the REF1 at the top of the stack
If you don't understand, I'll draw you a diagram to help you understand:
Assume that the JVM only executes the recursive steps that are inserted on the left tree:
The above bytecode instructions and illustrations are intercepted some key points to explain, if you want to further explore the children, you can contact me to discuss in detail.
Three or two fork Tree tool class:
1. Previous root sequence traversal: The root node is traversed first, then the left subtree is traversed, and the right subtree is traversed at last. (ABDHECFG)
2. Middle root sequence traversal: The left subtree is traversed first, then the root node is traversed, and the right subtree is traversed at last. (HDBEAFCG)
3. Post-root sequence traversal: Traverse the left subtree first, then traverse the right subtree, and finally traverse the root node (hdebfgca)
PackageTree;Importjava.util.ArrayList;Importjava.util.List;ImportJava.util.Stack; Public classBinarytreeutil {/*** Recursive implementation of the two-fork tree's pre-sequence traversal *@paramRoot *@return */ Public Static<T> list<t> Preordervisit (binarytreenode<t>root) {List<T> result=NewArraylist<>(); Preordervisit (Root,result); returnresult; } Private Static<T>voidPreordervisit (binarytreenode<t> node, list<t>result) { //If the node is empty, returns if(node==NULL){ return; } //is not empty, the value of the join nodeResult.add (Node.getdata ()); //first recursion left childpreordervisit (Node.getleft (), result); //and then recursive right childpreordervisit (Node.getright (), result); } /*** Recursive implementation of the two-fork tree in the middle sequence traversal *@paramRoot *@return */ Public Static<T> list<t> Inordervisit (binarytreenode<t>root) {List<T> result=NewArraylist<t>(); Inordervisit (Root,result); returnresult; } Private Static<T>voidInordervisit (binarytreenode<t> node, list<t>result) { if(node==NULL){ return; } inordervisit (Node.getleft (), result); Result.add (Node.getdata ()); Inordervisit (Node.getright (), result); } /*** Recursive implementation of two-fork tree after traversal *@paramRoot *@return */ Public Static<T> list<t> Postordervisit (binarytreenode<t>root) {List<T> result=NewArraylist<t>(); Postordervisit (Root,result); returnresult; } Private Static<T>voidPostordervisit (binarytreenode<t> node, list<t>result) { if(node==NULL){ return; } postordervisit (Node.getleft (), result); Postordervisit (Node.getright (), result); Result.add (Node.getdata ()); } /*** Implementation of pre-order traversal in a non-recursive manner *@paramRoot *@return */ Public Static<T> list<t> preordervisitwithoutrecursion (binarytreenode<t>root) {List<T> result=NewArraylist<t>(); Stack<BinaryTreeNode<T>> stack=NewStack<>(); if(root!=NULL) {Stack.push (root); } while(!Stack.isempty ()) {Binarytreenode<T> node=Stack.pop (); Result.add (Node.getdata ()); if(Node.getright ()! =NULL) {Stack.push (Node.getright ()); } if(Node.getleft ()! =NULL) {Stack.push (Node.getleft ()); } } returnresult; } /*** Implement the middle order traversal in a non-recursive way *@paramRoot *@return */ Public Static<T> list<t> inordervisitwithoutrecursion (binarytreenode<t>root) {List<T> result=NewArraylist<t>(); Stack<BinaryTreeNode<T>> stack=NewStack<>(); Binarytreenode<T> node=Root; while(node!=NULL|| !Stack.isempty ()) { while(node!=NULL) {Stack.push (node); Node=Node.getleft (); } Binarytreenode<T> currentnode=Stack.pop (); Result.add (Currentnode.getdata ()); Node=currentnode.getright (); } returnresult; }
The binary tree section above lists a total of 15 methods, and the main idea is to use recursion. About recursion, in order to let the baby understand what is going on, I also spent a little bit of thought to explain, please think about it further. It involves the knowledge of the JVM function call level, if you do not understand, it is recommended to look at the JVM book, understand how the JVM executes the code, it is easy to understand how recursion is executed.
"Binary tree" of Java recursion