通过不断迭代,编写<通过中缀表达式,构造表达式树>的代码

今天要练习的算法是通过中缀表达式生成表达式树。中缀、前缀、后缀表达式的概念就不赘述了,学习链接:中缀、前缀、后缀表达式

参考代码学习链接:表达式树—中缀表达式转换成后缀表达式(一)


 

  • 【迭代 ①】:识别单个运算符,进行分割,通过递归的思想构建表达式树。

举例:输入“1+2”,输出

Java code of phase[1]:

 1     void Express2BTree(String str){
 2         root=Express2BTreeProc(str);
 3     }
 4     private BTNode Express2BTreeProc(String str){
 5         BTNode parent=new BTNode();
 6         boolean isSet[]={false,false};    //【0】:left,【1】:right
 7         String tmp=new String();        //临时字符串
 8         for(int i=0;i<str.length();i++){
 9             char ch=str.charAt(i);
10             if(ch>=48 && ch<=57){            //是数字
11                 tmp+=ch;
12             }
13             else if(ch=='+' || ch=='-' || ch=='*' || ch=='/'){
14                 parent.data=String.valueOf(ch);
15                 if(! isSet[0]){            //左子树未构造
16                     isSet[0]=true;
17                     parent.lChild=Express2BTreeProc(tmp);
18                     tmp=new String("");    //归零初始化
19                 }
20             }
21         }
22         if(isSet[0] && (! isSet[1])){//右子树未构造
23             isSet[1]=true;
24             parent.rChild=Express2BTreeProc(tmp);
25             tmp=new String("");    //归零初始化
26         }
27         if(! isSet[0]) parent.data=tmp;//如果函数处理的全是数字(叶子节点),那么就返回叶子节点
28         return parent;
29     }

逻辑盲区:

1、启动构造右子树的 if  语句不能嵌套在上方的 if 中,否则不能触发。

2、数字0~9的ascii码是[ 48 , 57 ],故应写<=、>=。


  • 【迭代 ②】:判断多个表达式。

举例:输入“1+2+3”,输出:

代码改进:在临时字符串递加段,加入【或】判断条件 isSet[0] ,如果左子树已构造,继续扫描、递加。


  • 【迭代 ③】:识别优先级。*、/ 的优先级比+、- 的要高。

(在这里我修改了toString打印树函数,填充符由*变为space,避免混淆)

如果代码按原先的方式跑,结果是:

 

但是根据运算符优先级,应该是:

修改两处代码:

1.递归函数中引入 only_Have_Priority 变量:

1         boolean only_Have_Priority=false;
2         if(( str.indexOf("+")<0 && str.indexOf("-")<0 )  
3                             &&
4         ( str.indexOf("*")>=0 || str.indexOf("/")>=0 ))
5             only_Have_Priority=true;
6         //能够找到 * / 、不能找到 + -

2.触发对表达式进行分割的判断语句中引入一个【与】判断条件:

((!only_Have_Priority)&&(ch=='*' || ch=='/'))

完整代码:

Java code of phase[3]:

 1     void Express2BTree(String str){
 2         root=Express2BTreeProc(str);
 3     }
 4     private BTNode Express2BTreeProc(String str){
 5         BTNode parent=new BTNode();
 6         int i;
 7         boolean isSet[]={false,false};    //【0】:left,【1】:right
 8     //    boolean havaAddOrSub = ( str.indexOf("+")<0 || str.indexOf("-")<0 ) ? false : true;
 9         
10         boolean only_Have_Priority=false;
11         if(( str.indexOf("+")<0 && str.indexOf("-")<0 )  
12                             &&
13         ( str.indexOf("*")>=0 || str.indexOf("/")>=0 ))
14             only_Have_Priority=true;
15         //能够找到 * / 、不能找到 + -
16         
17         String tmp=new String();        //临时字符串
18         
19         for(i=0;i<str.length();i++){
20             char ch=str.charAt(i);    //是数字、或者左树已构造  || (havaAddOrSub && (ch=='' || ch=='-') )   
21             if( (ch>=48 && ch<=57 ) || isSet[0] || ((!only_Have_Priority)&&(ch=='*' || ch=='/'))   ){
22                 tmp+=ch;
23             }
24             else if(ch=='+' || ch=='-' || ch=='*' || ch=='/'){
25                 parent.data=String.valueOf(ch);
26                 if(! isSet[0]){            //左子树未构造
27                     isSet[0]=true;
28                     parent.lChild=Express2BTreeProc(tmp);
29                     tmp=new String("");    //归零初始化
30                 }
31             }
32         }

逻辑盲点:

对 only_Have_Priority 进行赋值时,应该是【与】而不是或。想错了。

测试:

输入:1*2+3*4

输出:

输入:1*2+3*4+5*6

输出:


  • 【迭代 ④】:小括号的优先级应最高

 运行中出现bug。经查是原来的 only_Have_Priority  判断语句的不足。修改之。

加入了堆栈思想的括号判断语句。

Java code of phase[4]:

 1     void Express2BTree(String str){
 2         root=Express2BTreeProc(str);
 3     }
 4     private BTNode Express2BTreeProc(String str){
 5         BTNode parent=new BTNode();
 6         int i;
 7         boolean isSet[]={false,false};    //【0】:left,【1】:right
 8     //    boolean havaAddOrSub = ( str.indexOf("+")<0 || str.indexOf("-")<0 ) ? false : true;
 9         
10         boolean only_Have_Priority=false;
11         int inBracket=0;        //判断当前字符是否在括号中    
12                 
13         boolean havaMulti=false;
14         boolean havaAdd=false;
15         for(i=0;i<str.length();i++){
16             char ch=str.charAt(i);
17             if(ch=='(') inBracket++;
18             else if(ch==')') inBracket--;
19             else if(inBracket==0){            //在括号内
20                 if(ch=='*' || ch == '/') havaMulti=true;
21                 else if(ch=='-' || ch == '+') havaAdd=true;
22             }
23         }
24         if((!havaAdd) && (havaMulti)) only_Have_Priority=true;
25         //能够找到 * / 、不能找到 + -
26         
27         inBracket=0;
28         
29         String tmp=new String();        //临时字符串
30         
31         for(i=0;i<str.length();i++){
32             char ch=str.charAt(i);    //是数字、或者左树已构造  
33             if(ch=='('){
34                 if(inBracket>0) tmp+=ch;//括号内的括号
35                 inBracket++;
36             }
37             else if(ch==')'){
38                 inBracket--;
39                 if(inBracket>0) tmp+=ch;
40             }
41             else if( (ch>=48 && ch<=57 ) 
42                     || isSet[0] 
43                     || ((!only_Have_Priority)&&(ch=='*' || ch=='/')) //不存在(只有1*2),也就是1*2+3
44                     || inBracket>0  ){
45                 tmp+=ch;
46             }
47             else if(ch=='+' || ch=='-' || ch=='*' || ch=='/'){
48                 parent.data=String.valueOf(ch);
49                 if(! isSet[0]){            //左子树未构造
50                     isSet[0]=true;
51                     parent.lChild=Express2BTreeProc(tmp);
52                     tmp=new String("");    //归零初始化
53                 }
54             }
55         }
56         
57         if(isSet[0] && (! isSet[1])){//右子树未构造
58             isSet[1]=true;
59             parent.rChild=Express2BTreeProc(tmp);
60             tmp=new String("");    //归零初始化
61         }
62         if(! isSet[0]) parent.data=tmp;//如果函数处理的全是数字(叶子节点),那么就返回叶子节点
63         return parent;
64     }

测试输入:((3*4)/(1+2))*((1+1)/(1-2))

测试输出:

测试输入:(1+2)*3

测试输出:


【在一次测试中发现异常】:

输入:(1+2)*3-2

输出:

然后改了一个小时bug。我的函数写的还是有问题,反正现在无论怎么输入,只要是一个正常的表达式,都没什么问题了。

修改BUG后代码:

 1     void Express2BTree(String str){
 2         root=Express2BTreeProc(str);
 3     }
 4     private BTNode Express2BTreeProc(String str){
 5         int i;
 6         //首尾括号剥夺
 7         if(str.length()>1 && str.charAt(0)=='(' && str.charAt(str.length()-1)==')'){
 8             String tmp=str.substring(1, str.length()-1);
 9             //是否存在括号内字符?
10             boolean haveInnerChar=false;
11             int inBracket=0;    
12             for(i=0;i<str.length();i++){
13                 char ch=str.charAt(i);
14                 if(ch=='(') inBracket++;
15                 else if(ch==')') inBracket--;
16                 else if(inBracket==0){            //在括号内
17                     haveInnerChar=true;
18                 }
19             }
20             if(!haveInnerChar) str=tmp;
21         }
22         BTNode parent=new BTNode();
23 
24         boolean isSet[]={false,false};    //【0】:left,【1】:right
25     //    boolean havaAddOrSub = ( str.indexOf("+")<0 || str.indexOf("-")<0 ) ? false : true;
26         
27         boolean only_Have_Priority=false;
28         int inBracket=0;        //判断当前字符是否在括号中    
29         
30 /*        if(( str.indexOf("+")<0 && str.indexOf("-")<0 )  
31                             &&
32         ( str.indexOf("*")>=0 || str.indexOf("/")>=0 ))
33             only_Have_Priority=true;*/
34         boolean havaMulti=false;
35         boolean havaAdd=false;
36         for(i=0;i<str.length();i++){
37             char ch=str.charAt(i);
38             if(ch=='(') inBracket++;
39             else if(ch==')') inBracket--;
40             else if(inBracket==0){            //在括号内
41                 if(ch=='*' || ch == '/') havaMulti=true;
42                 else if(ch=='-' || ch == '+') havaAdd=true;
43             }
44         }
45         if((!havaAdd) && (havaMulti)) only_Have_Priority=true;
46         //能够找到 * / 、不能找到 + -
47         
48         inBracket=0;
49         
50         String tmp=new String();        //临时字符串
51         
52         for(i=0;i<str.length();i++){
53             char ch=str.charAt(i);    //是数字、或者左树已构造  
54             if(ch=='('){
55                 tmp+=ch;//括号内的括号
56                 inBracket++;
57             }
58             else if(ch==')'){
59                 inBracket--;
60                 tmp+=ch;
61             }
62             else if( (ch>=48 && ch<=57 ) 
63                     || isSet[0] 
64                     || ((!only_Have_Priority)&&(ch=='*' || ch=='/')) //不存在(只有1*2),也就是1*2+3
65                     || inBracket>0  ){
66                 tmp+=ch;
67             }
68             else if(ch=='+' || ch=='-' || ch=='*' || ch=='/'){
69                 parent.data=String.valueOf(ch);
70                 if(! isSet[0]){            //左子树未构造
71                     isSet[0]=true;
72                     parent.lChild=Express2BTreeProc(tmp);
73                     tmp=new String("");    //归零初始化
74                 }
75             }
76         }
77         
78         if(isSet[0] && (! isSet[1])){//右子树未构造
79             isSet[1]=true;
80             parent.rChild=Express2BTreeProc(tmp);
81             tmp=new String("");    //归零初始化
82         }
83         if(! isSet[0]) parent.data=tmp;//如果函数处理的全是数字(叶子节点),那么就返回叶子节点
84         return parent;
85     }
View Code

完整代码:

  1 import java.util.*;
  2 
  3 public class demo {
  4     public static void main(String args[]){
  5 
  6 /*        tree.Express2BTree("((3*4)/(1+2))*((1+1)/(1-2))");
  7         System.out.println(tree);*/
  8         BTtree tree=new BTtree();
  9         tree.splitCh=' ';
 10         Scanner scan;
 11         int flag=10;
 12         while(flag>0){
 13             flag--;
 14             scan=new Scanner(System.in);//generate input flu
 15             System.out.print("请输入中缀表达式: ");//input reminder
 16             String str=new String(scan.nextLine());//assignment
 17             tree.Express2BTree(str);
 18             System.out.println("前缀表达式: ");//input reminder
 19             tree.PreOrderTraversal();
 20             System.out.println("后缀表达式: ");//input reminder
 21             tree.PostOrderTraversal();
 22         }
 23         scan=new Scanner(System.in);
 24         scan.close();
 25 
 26     }
 27 }
 28 
 29 class BTtree{//二叉树类
 30     class BTNode{//节点类
 31         String data=new String("0");
 32         BTNode lChild=null;
 33         BTNode rChild=null;
 34         boolean LTag=false;//=0 : 指向左孩子。 =1 : 指向前驱
 35         boolean RTag=false;//=0 : 指向右孩子。 =1 : 指向后继
 36         int height=1;        //用于AVL树
 37         BTNode(){}
 38         BTNode(String data){this.data=data;}
 39         BTNode(int num){this.data=Integer.toString(num);};
 40     }
 41     void Express2BTree(String str){
 42         root=Express2BTreeProc(str);
 43     }
 44     private BTNode Express2BTreeProc(String str){
 45         int i;
 46         //首尾括号剥夺
 47         if(str.length()>1 && str.charAt(0)=='(' && str.charAt(str.length()-1)==')'){
 48             String tmp=str.substring(1, str.length()-1);
 49             //是否存在括号内字符?
 50             boolean haveInnerChar=false;
 51             int inBracket=0;    
 52             for(i=0;i<str.length();i++){
 53                 char ch=str.charAt(i);
 54                 if(ch=='(') inBracket++;
 55                 else if(ch==')') inBracket--;
 56                 else if(inBracket==0){            //在括号内
 57                     haveInnerChar=true;
 58                 }
 59             }
 60             if(!haveInnerChar) str=tmp;
 61         }
 62         BTNode parent=new BTNode();
 63 
 64         boolean isSet[]={false,false};    //【0】:left,【1】:right
 65     //    boolean havaAddOrSub = ( str.indexOf("+")<0 || str.indexOf("-")<0 ) ? false : true;
 66         
 67         boolean only_Have_Priority=false;
 68         int inBracket=0;        //判断当前字符是否在括号中    
 69         
 70 /*        if(( str.indexOf("+")<0 && str.indexOf("-")<0 )  
 71                             &&
 72         ( str.indexOf("*")>=0 || str.indexOf("/")>=0 ))
 73             only_Have_Priority=true;*/
 74         boolean havaMulti=false;
 75         boolean havaAdd=false;
 76         for(i=0;i<str.length();i++){
 77             char ch=str.charAt(i);
 78             if(ch=='(') inBracket++;
 79             else if(ch==')') inBracket--;
 80             else if(inBracket==0){            //在括号内
 81                 if(ch=='*' || ch == '/') havaMulti=true;
 82                 else if(ch=='-' || ch == '+') havaAdd=true;
 83             }
 84         }
 85         if((!havaAdd) && (havaMulti)) only_Have_Priority=true;
 86         //能够找到 * / 、不能找到 + -
 87         
 88         inBracket=0;
 89         
 90         String tmp=new String();        //临时字符串
 91         
 92         for(i=0;i<str.length();i++){
 93             char ch=str.charAt(i);    //是数字、或者左树已构造  
 94             if(ch=='('){
 95                 tmp+=ch;//括号内的括号
 96                 inBracket++;
 97             }
 98             else if(ch==')'){
 99                 inBracket--;
100                 tmp+=ch;
101             }
102             else if( (ch>=48 && ch<=57 ) 
103                     || isSet[0] 
104                     || ((!only_Have_Priority)&&(ch=='*' || ch=='/')) //不存在(只有1*2),也就是1*2+3
105                     || inBracket>0  ){
106                 tmp+=ch;
107             }
108             else if(ch=='+' || ch=='-' || ch=='*' || ch=='/'){
109                 parent.data=String.valueOf(ch);
110                 if(! isSet[0]){            //左子树未构造
111                     isSet[0]=true;
112                     parent.lChild=Express2BTreeProc(tmp);
113                     tmp=new String("");    //归零初始化
114                 }
115             }
116         }
117         
118         if(isSet[0] && (! isSet[1])){//右子树未构造
119             isSet[1]=true;
120             parent.rChild=Express2BTreeProc(tmp);
121             tmp=new String("");    //归零初始化
122         }
123         if(! isSet[0]) parent.data=tmp;//如果函数处理的全是数字(叶子节点),那么就返回叶子节点
124         return parent;
125     }
126     
127     protected BTNode root=new BTNode();
128     BTtree(){
129     }
130     BTtree(int layer){
131         //用队列的方式构造n层树
132         List<BTNode> queue=new ArrayList<BTNode>();
133         int front=0;
134         int rear=0;//队尾插入
135         queue.add(root);//初始化入队
136         rear++;
137         int i , k=0 , j;
138         for(j=0;j<layer;j++){
139             int nowRear=rear;
140             for(i=front;i<nowRear;i++){
141                 //出队,生两个孩子
142                 BTNode parent=queue.get(front++);
143                 BTNode lChild=new BTNode();
144                 lChild.data=Integer.toString(++k);
145                 BTNode rChild=new BTNode();
146                 rChild.data=Integer.toString(++k);
147                 parent.lChild=lChild;
148                 parent.rChild=rChild;
149                 queue.add(lChild);
150                 rear++;
151                 queue.add(rChild);
152                 rear++;
153             }
154         }
155     }
156     BTtree(String express){//通过中缀表达式进行构造
157         //1.对表达式进行括号补全。
158         
159         
160     }
161     public String toString(){//重写打印函数
162         String padding=new String(" ");
163         List<BTNode> queue=new ArrayList<BTNode>();
164         List<String[]> PrintList=new ArrayList<String[]>();
165         int front=0;
166         int rear=0;//队尾插入
167         queue.add(root);//初始化入队
168         rear++;
169         int i , k=0 , j;
170         
171         String emptySignal=new String("");//空信号
172         
173         String str[]=new String[1];
174         str[0]=root.data;
175         PrintList.add(str);//打印数据结构初始化
176         int layer=1;//下一层字符串的数目是2^1=2。
177         int pos=0;
178         
179         boolean flag=true;
180         ok:
181         while(flag){
182             pos=0;//pos初始化
183             String tmp[]=new String[(int)Math.pow((int)2, (int)(layer++))];//length=2^layer
184             flag=false;        //循环标志初始化
185             int nowRear=rear;
186             int nowFront=front;
187             for(i=front;i<nowRear;i++){
188                 String nowStr=new String();
189                 BTNode parent=queue.get(front++);
190                 if(parent==null) break ok;    //跳出两重循环
191                 if(parent.data.equals(emptySignal)){//如果是空的,派生出两个空孩子
192                     for(int t=0;t<2;t++){
193                         tmp[pos++]=padding;
194                         BTNode empty=new BTNode();
195                         empty.data=emptySignal;
196                         queue.add(empty);rear++;
197                     }
198                 }else{
199                     if(parent.lChild!=null){
200                         flag=true;                    //只要这一层存在孩子,就可以继续循环下去。
201                         queue.add(parent.lChild);
202                         tmp[pos++]=parent.lChild.data;
203                         rear++;
204                     }else{
205                         tmp[pos++]=padding;
206                         BTNode empty=new BTNode();
207                         empty.data=emptySignal;
208                         queue.add(empty);
209                         rear++;
210                     }
211                     if(parent.rChild!=null){
212                         flag=true;
213                         queue.add(parent.rChild);
214                         tmp[pos++]=parent.rChild.data;
215                         rear++;
216                     }else{
217                         tmp[pos++]=padding;
218                         BTNode empty=new BTNode();
219                         empty.data=emptySignal;
220                         queue.add(empty);
221                         rear++;
222                     }
223                 }
224             }                // end of for
225             PrintList.add(tmp);
226         }                    // end of while
227         /*
228         for(i=0;i<PrintList.size();i++){
229             for(j=0;j<PrintList.get(i).length;j++) System.out.print(PrintList.get(i)[j]+" ");
230             System.out.println();
231         }*/
232         //后处理
233         String[] PrintListLine=new String[PrintList.size()-1];
234         for(i=PrintListLine.length-1;i>=0;i--){//循环构造
235             //首先进行构造
236             String tmp=new String();
237             for(j=0;j<PrintList.get(i).length;j++){
238                 tmp+=PrintList.get(i)[j];
239                 if(j!=PrintList.get(i).length-1) tmp+=" ";
240             }
241             PrintListLine[i]=tmp;
242         }
243         for(i=PrintListLine.length-2;i>=0;i--){//居中操作
244             int spaceNum=(PrintListLine[i+1].length()-PrintListLine[i].length())/2;
245             String space=new String();
246             for(int t=0;t<spaceNum;t++) space+=" ";
247             PrintListLine[i]=space+PrintListLine[i]+space;
248         }    
249         String outStr=new String();
250         for(i=0;i<PrintListLine.length;i++){//最后构造一个字符串
251             outStr+=PrintListLine[i]+"
";
252         }
253         return outStr;
254     }
255     void PreOrderTraversal(){
256         PreOrder(root);
257         System.out.println();
258     }
259     char splitCh=',';
260     private void PreOrder(BTNode obj){
261         if(obj!=null){
262             System.out.print(obj.data+splitCh);
263             PreOrder(obj.lChild);
264             PreOrder(obj.rChild);
265         }
266     }
267     void InOrderTraversal(){
268         InOrder(root);
269         System.out.println();
270     }
271     private void InOrder(BTNode obj){    
272         if(obj!=null){
273             InOrder(obj.lChild);
274             System.out.print(obj.data+splitCh);
275             InOrder(obj.rChild);
276         }
277     }
278     void PostOrderTraversal(){
279         PostOrder(root);
280         System.out.println();
281     }
282     private void PostOrder(BTNode obj){    
283         if(obj!=null){
284             
285             InOrder(obj.lChild);
286             InOrder(obj.rChild);
287             System.out.print(obj.data+splitCh);
288         }
289     }
290 }
291 
292 
293 
294 //线索二叉树
295 class BThrTree extends BTtree{
296     BThrTree(BTtree obj){//由父类构造而来
297         //首先拷贝根节点
298         BTNode tmp=new BTNode();
299         tmp.data=obj.root.data;
300         copy(root,obj.root);
301     }
302     void copy(BTNode node1,BTNode node2){
303         if(node2.lChild!=null){//左树递归
304             BTNode l=new BTNode();
305             l.data=node2.lChild.data;//拷贝左树    
306             node1.lChild=l;//左树赋值            
307             copy(node1.lChild,node2.lChild);
308         }
309         if(node2.rChild!=null){//右树递归
310             BTNode r=new BTNode();
311             r.data=node2.rChild.data;//拷贝右树
312             node1.rChild=r;//右树赋值
313             copy(node1.rChild,node2.rChild);
314         }    
315     }
316     public void InThreadingFabric(){//中序线索化构造
317         BTNode now=root;
318         InThreading(now); 
319         pre.RTag=true;//【最后一个后继为null】
320         pre.rChild=null;
321     }
322     private BTNode pre=null;//前驱指针
323     private void InThreading(BTNode node){//中序线索化递归
324         if(node!=null){//保证节点非空
325             InThreading(node.lChild);//左子树线索化
326             if(node.lChild==null){//如果左子树不存在
327                 node.LTag=true;//线索化
328                 node.lChild=pre;//前驱    【第一个前驱为null】
329             }
330             if(pre!=null && pre.rChild==null){//后继
331                 pre.RTag=true;
332                 pre.rChild=node;
333             }
334             pre=node;//保持pre指向node的前驱。
335             InThreading(node.rChild);//左子树线索化
336         }
337     }
338     void InOrderTraversal_Thr(){//线索化遍历
339         BTNode now=root;
340         //遍历前驱
341         while(now.lChild!=null){//要么有左子树。
342             now=now.lChild;
343         }
344         while(now!=null){//要么有左子树。
345             System.out.print(now.data+",");
346             if(now.RTag){now=now.rChild;}//如果是后继,就继续后继。
347             else{
348                 now=now.rChild;//如果不是,则令右子树的最左节点为后继
349                 while(!now.LTag) now=now.lChild;
350             }
351         }
352         System.out.println();
353     }
354 }
355 
356 
357 class SearchBST extends BTtree{//二叉查找树
358     SearchBST(int[] nums){//由二维数组构造
359         root.data=String.valueOf(nums[0]);//构造根节点
360         for(int i=1;i<nums.length;i++){//对其他元素进行构造
361             BTNode node=new BTNode();
362             node.data=String.valueOf(nums[i]);//构造叶子节点
363             BTNode parent=root;
364             int nodeV=nums[i];
365             while(parent!=null){
366                 int parentV=Integer.valueOf(parent.data).intValue();//当前根节点的值
367                 if(nodeV<parentV){//左叶子
368                     if(parent.lChild==null){//当前根节点的左叶子非空
369                         parent.lChild=node;//挂入节点
370                         break;                //如果这里没有加【break】,就会死循环。待解决☆☆☆
371                     }
372                     parent=parent.lChild;//如果这里空了,跳出循环
373                 }else{
374                     if(parent.rChild==null){
375                         parent.rChild=node;//挂入节点
376                         break;                //☆☆☆
377                     }
378                     parent=parent.rChild;//如果这里空了,跳出循环                    
379                 }
380             }
381         }
382     }
383     SearchBST(){}
384 }
385 
386 class AVLTree extends BTtree{    //平衡二叉树
387     AVLTree(int[] nums){//由二维数组构造
388         root.data=String.valueOf(nums[0]);
389         for(int i=1;i<nums.length;i++) AVLinsert(root,null,true,String.valueOf(nums[i]));
390     }
391     BTNode LLRotate(BTNode node){//左子树.高度-右子树.高度==2 【向右旋转】
392         /*
393          * 根节点的左孩子  为新的根节点。
394          * 老根节点成为新根节点的右孩子
395          * 根节点的左孩子  的右子树作为 老根节点的左子树
396         */ 
397         BTNode pre=node;
398         node=node.lChild;//根节点的左孩子  为新的根节点。
399         //从此之后node就是【根节点的左孩子】
400         pre.lChild=node.rChild;//根节点的左孩子(node)  的右子树作为 老根节点(pre)的左子树
401         node.rChild=pre;
402         //pre: 老根节点
403         pre.height=Math.max(getHeight(pre.lChild), getHeight(pre.rChild))+1;//递归增加树的高度
404         node.height=Math.max(getHeight(node.lChild), getHeight(node.rChild))+1;//递归增加树的高度
405         return node;//返回根节点
406     }
407     
408     BTNode RRRotate(BTNode node){//左子树.高度-右子树.高度==-2 【向左旋转】
409         /*
410          * 根节点的左孩子  为新的根节点。
411          * 老根节点成为新根节点的右孩子
412          * 根节点的左孩子  的右子树作为 老根节点的左子树
413          */    
414         BTNode pre=node;
415         node=node.rChild;//根节点的右孩子  为新的根节点。
416         //从此之后node就是【根节点的左孩子】
417         pre.rChild=node.lChild;//根节点的左孩子(node)  的右子树作为 老根节点(pre)的左子树
418         node.lChild=pre;
419         //pre: 老根节点
420         pre.height=Math.max(getHeight(pre.lChild), getHeight(pre.rChild))+1;//递归增加树的高度
421         node.height=Math.max(getHeight(node.lChild), getHeight(node.rChild))+1;//递归增加树的高度
422         return node;
423     }
424     
425     BTNode LRRotate(BTNode node){//左子树.高度-右子树.高度==2 【向右旋转】
426         node.lChild=RRRotate(node.lChild);
427         node=LLRotate(node);
428         return node;
429     }
430     
431     BTNode RLRotate(BTNode node){//左子树.高度-右子树.高度==2 【向右旋转】
432         node.rChild=LLRotate(node.rChild);
433         node=RRRotate(node);
434         return node;
435     }
436     //                  当前节点           父节点               
437     void AVLinsert(BTNode node,BTNode parent,boolean isLeft,String data){
438         int dataV=Integer.valueOf(data).intValue();
439         int nodeV=0;
440         if(node!=null) nodeV=Integer.valueOf(node.data).intValue();
441         if(node==null){
442             BTNode newNode=new BTNode();
443             newNode.data=data;
444             if(isLeft) parent.lChild=newNode;
445             else        parent.rChild=newNode;
446         }
447         
448         else if(dataV<nodeV){//向左插入
449             AVLinsert(node.lChild,node,true,data);
450             node.height=Math.max(getHeight(node.lChild), getHeight(node.rChild))+1;//递归增加树的高度
451             
452             System.out.println("sub="+(getHeight(node.lChild)-getHeight(node.rChild)));
453             System.out.println("node="+node.data);
454             
455             if(getHeight(node.lChild)-getHeight(node.rChild)==2){
456                 System.out.println("L变形前
"+this);
457                 if(getHeight(node.lChild.lChild)>getHeight(node.lChild.rChild)){
458                     System.out.println("LL");
459                     boolean flag=false;
460                     if(root.data.equals(node.data)) flag=true;
461                     if(!flag){
462                         if(isLeft) parent.lChild=LLRotate(node);
463                         else parent.rChild=LLRotate(node);
464                     }else node=LLRotate(node);
465                     if(flag) root=node;
466                 }else{
467                     System.out.println("LR");
468                     boolean flag=false;
469                     if(root.data.equals(node.data)) flag=true;
470                     if(!flag){
471                         if(isLeft) parent.lChild=LRRotate(node);
472                         else parent.rChild=LRRotate(node);
473                     }else node=LRRotate(node);
474                     if(flag) root=node;
475                 }
476                 System.out.println("变形后
"+this);
477             }
478             System.out.println(this);
479             
480         }else{
481             AVLinsert(node.rChild,node,false,data);
482             node.height=Math.max(getHeight(node.lChild), getHeight(node.rChild))+1;//递归增加树的高度
483             
484             System.out.println("sub="+(getHeight(node.lChild)-getHeight(node.rChild)));
485             System.out.println("node="+node.data);
486             
487             if(getHeight(node.lChild)-getHeight(node.rChild)==-2){
488                 System.out.println("R变形前
"+this);
489                 if(getHeight(node.rChild.lChild)>getHeight(node.rChild.rChild)){
490                     System.out.println("RL");
491                     boolean flag=false;
492                     if(root.data.equals(node.data)) flag=true;
493                     if(!flag){
494                         if(isLeft) parent.lChild=RLRotate(node);
495                         else parent.rChild=RLRotate(node);
496                     }else node=RLRotate(node);
497                     if(flag) root=node;
498                 }else{
499                     System.out.println("RR");
500                     boolean flag=false;
501                     if(root.data.equals(node.data)) flag=true;
502                     if(!flag){
503                         if(isLeft) parent.lChild=RRRotate(node);
504                         else parent.rChild=RRRotate(node);
505                     }else node=RRRotate(node);
506                     if(flag) root=node;
507                 }
508                 System.out.println("变形后
"+this);
509             }
510             System.out.println(this);
511         }
512     }
513     
514     int getHeight(BTNode node){
515         if(node!=null){
516             return node.height;
517         }else{
518             return 0;
519         }
520     }
521     void test(){
522         root=new BTNode(0);
523         BTNode node[]=new BTNode[3];
524         for(int i=0;i<3;i++) node[i]=new BTNode(i+1);
525         root.lChild=node[0];
526         root.lChild.rChild=node[1];
527         root.lChild.lChild=node[2];
528         System.out.println(this);
529         root=LRRotate(root);
530         System.out.println(this);
531         System.out.println(root.height);
532         System.out.println(root.lChild.height);
533         System.out.println(root.rChild.height);
534     }
535     AVLTree(){}
536 }
View Code

程序运行结果:

原文地址:https://www.cnblogs.com/TQCAI/p/7635089.html