通过不断迭代,编写<通过中缀表达式,构造表达式树>的代码
今天要练习的算法是通过中缀表达式生成表达式树。中缀、前缀、后缀表达式的概念就不赘述了,学习链接:中缀、前缀、后缀表达式。
参考代码学习链接:表达式树—中缀表达式转换成后缀表达式(一)。
- 【迭代 ①】:识别单个运算符,进行分割,通过递归的思想构建表达式树。
举例:输入“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 }
完整代码:
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]+"\n"; 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变形前\n"+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("变形后\n"+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变形前\n"+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("变形后\n"+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 }
程序运行结果: