二叉排序树BST
Posted TQCAI
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二叉排序树BST相关的知识,希望对你有一定的参考价值。
今天没花20分钟,就把BST的代码写出来了。毕竟寒假学了一遍,脑子里有影响,也很好理解。
只是出现了两个问题:
1.我在编写while循环的时候,就想到了新建叶子节点之后就break。但是,我又“机智”的想到,while(parent!=null)语句就可以检测循环的结束了,不关有没有新建叶子节点,都可以直接写parent=parent.child语句,进入下一个循环。因为如果没有新建叶子节点,parent就会变成null,从而跳出循环。
但是我想错了。如果找到了并新建叶子节点,再执行parent=parent.child语句就会使parent变成新建的那个节点,从而无线循环下去。(我按了F5等着出结果呢,结果风扇沙沙吹,CPU快烧坏了)
解决方法:加入break语句。
总结:算法结构不能想当然。以及懂的调试。
2.我调用以前写的 toString 函数进行打印。结果出现空指针错误。经查是一个老bug,浪费了很多时间。
BST的Java代码:
1 class SearchBST extends BTtree{//二叉查找树 2 SearchBST(int[] nums){//由二维数组构造 3 root.data=String.valueOf(nums[0]);//构造根节点 4 for(int i=1;i<nums.length;i++){//对其他元素进行构造 5 BTNode node=new BTNode(); 6 node.data=String.valueOf(nums[i]);//构造叶子节点 7 BTNode parent=root; 8 int nodeV=nums[i]; 9 while(parent!=null){ 10 int parentV=Integer.valueOf(parent.data).intValue();//当前根节点的值 11 if(nodeV<parentV){//左叶子 12 if(parent.lChild==null){//当前根节点的左叶子非空 13 parent.lChild=node;//挂入节点 14 break; //如果这里没有加【break】,就会死循环。待解决☆☆☆ 15 } 16 parent=parent.lChild;//如果这里空了,跳出循环 17 }else{ 18 if(parent.rChild==null){ 19 parent.rChild=node;//挂入节点 20 break; //☆☆☆ 21 } 22 parent=parent.rChild;//如果这里空了,跳出循环 23 } 24 } 25 } 26 } 27 SearchBST(){} 28 }
打印输出:(*代表空)
补充一个递归算法:
void AVLinsert(BTNode node,BTNode parent,boolean isLeft,String data){ int dataV=Integer.valueOf(data).intValue(); int nodeV=0; if(node!=null) nodeV=Integer.valueOf(node.data).intValue(); BTNode newNode=new BTNode(); newNode.data=data; if(node==null){ if(isLeft) parent.lChild=newNode; else parent.rChild=newNode; } else if(dataV<nodeV){//向左插入 AVLinsert(node.lChild,node,true,data); }else{ AVLinsert(node.rChild,node,false,data); } }
完整代码:
1 import java.util.*; 2 3 public class demo { 4 public static void main(String args[]){ 5 BTtree tree=new BTtree(3); 6 tree.InOrderTraversal(); 7 System.out.print(tree); 8 BThrTree thrTree=new BThrTree(tree); 9 thrTree.InOrderTraversal(); 10 thrTree.InThreadingFabric(); 11 thrTree.InOrderTraversal_Thr(); 12 int []nums={45,12,53,3,37,24,100,61,90,78}; 13 SearchBST bst=new SearchBST(nums); 14 bst.PreOrderTraversal(); 15 System.out.println(bst); 16 // thrTree.InOrderTraversal_Thr(); 17 } 18 } 19 20 class BTtree{//二叉树类 21 class BTNode{//节点类 22 String data=new String("0");; 23 BTNode lChild=null; 24 BTNode rChild=null; 25 boolean LTag=false;//=0 : 指向左孩子。 =1 : 指向前驱 26 boolean RTag=false;//=0 : 指向右孩子。 =1 : 指向后继 27 } 28 protected BTNode root=new BTNode(); 29 BTtree(){ 30 } 31 BTtree(int layer){ 32 //用队列的方式构造n层树 33 List<BTNode> queue=new ArrayList<BTNode>(); 34 int front=0; 35 int rear=0;//队尾插入 36 queue.add(root);//初始化入队 37 rear++; 38 int i , k=0 , j; 39 for(j=0;j<layer;j++){ 40 int nowRear=rear; 41 for(i=front;i<nowRear;i++){ 42 //出队,生两个孩子 43 BTNode parent=queue.get(front++); 44 BTNode lChild=new BTNode(); 45 lChild.data=Integer.toString(++k); 46 BTNode rChild=new BTNode(); 47 rChild.data=Integer.toString(++k); 48 parent.lChild=lChild; 49 parent.rChild=rChild; 50 queue.add(lChild); 51 rear++; 52 queue.add(rChild); 53 rear++; 54 } 55 } 56 } 57 BTtree(String express){//通过中缀表达式进行构造 58 //1.对表达式进行括号补全。 59 60 61 } 62 public String toString(){//重写打印函数 63 List<BTNode> queue=new ArrayList<BTNode>(); 64 List<String[]> PrintList=new ArrayList<String[]>(); 65 int front=0; 66 int rear=0;//队尾插入 67 queue.add(root);//初始化入队 68 rear++; 69 int i , k=0 , j; 70 71 String emptySignal=new String("");//空信号 72 73 String str[]=new String[1]; 74 str[0]=root.data; 75 PrintList.add(str);//打印数据结构初始化 76 int layer=1;//下一层字符串的数目是2^1=2。 77 int pos=0; 78 79 boolean flag=true; 80 ok: 81 while(flag){ 82 pos=0;//pos初始化 83 String tmp[]=new String[(int)Math.pow((int)2, (int)(layer++))];//length=2^layer 84 flag=false; //循环标志初始化 85 int nowRear=rear; 86 int nowFront=front; 87 for(i=front;i<nowRear;i++){ 88 String nowStr=new String(); 89 BTNode parent=queue.get(front++); 90 if(parent==null) break ok; //跳出两重循环 91 if(parent.data.equals(emptySignal)){//如果是空的,派生出两个空孩子 92 for(int t=0;t<2;t++){ 93 tmp[pos++]="*"; 94 BTNode empty=new BTNode(); 95 empty.data=emptySignal; 96 queue.add(empty);rear++; 97 } 98 }else{ 99 if(parent.lChild!=null){ 100 flag=true; //只要这一层存在孩子,就可以继续循环下去。 101 queue.add(parent.lChild); 102 tmp[pos++]=parent.lChild.data; 103 rear++; 104 }else{ 105 tmp[pos++]="*"; 106 BTNode empty=new BTNode(); 107 empty.data=emptySignal; 108 queue.add(empty); 109 rear++; 110 } 111 if(parent.rChild!=null){ 112 flag=true; 113 queue.add(parent.rChild); 114 tmp[pos++]=parent.rChild.data; 115 rear++; 116 }else{ 117 tmp[pos++]="*"; 118 BTNode empty=new BTNode(); 119 empty.data=emptySignal; 120 queue.add(empty); 121 rear++; 122 } 123 } 124 } // end of for 125 PrintList.add(tmp); 126 } // end of while 127 /* 128 for(i=0;i<PrintList.size();i++){ 129 for(j=0;j<PrintList.get(i).length;j++) System.out.print(PrintList.get(i)[j]+" "); 130 System.out.println(); 131 }*/ 132 //后处理 133 String[] PrintListLine=new String[PrintList.size()-1]; 134 for(i=PrintListLine.length-1;i>=0;i--){//循环构造 135 //首先进行构造 136 String tmp=new String(); 137 for(j=0;j<PrintList.get(i).length;j++){ 138 tmp+=PrintList.get(i)[j]; 139 if(j!=PrintList.get(i).length-1) tmp+=" "; 140 } 141 PrintListLine[i]=tmp; 142 } 143 for(i=PrintListLine.length-2;i>=0;i--){//居中操作 144 int spaceNum=(PrintListLine[i+1].length()-PrintListLine[i].length())/2; 145 String space=new String(); 146 for(int t=0;t<spaceNum;t++) space+=" "; 147 PrintListLine[i]=space+PrintListLine[i]+space; 148 } 149 String outStr=new String(); 150 for(i=0;i<PrintListLine.length;i++){//最后构造一个字符串 151 outStr+=PrintListLine[i]+"\\n"; 152 } 153 return outStr; 154 } 155 void PreOrderTraversal(){ 156 PreOrder(root); 157 System.out.println(); 158 } 159 void PreOrder(BTNode obj){ 160 if(obj!=null){ 161 System.out.print(obj.data+","); 162 PreOrder(obj.lChild); 163 PreOrder(obj.rChild); 164 } 165 } 166 void InOrderTraversal(){ 167 InOrder(root); 168 System.out.println(); 169 } 170 void InOrder(BTNode obj){ 171 if(obj!=null){ 172 InOrder(obj.lChild); 173 System.out.print(obj.data+","); 174 InOrder(obj.rChild); 175 } 176 } 177 } 178 179 180 181 //线索二叉树 182 class BThrTree extends BTtree{ 183 BThrTree(BTtree obj){//由父类构造而来 184 //首先拷贝根节点 185 BTNode tmp=new BTNode(); 186 tmp.data=obj.root.data; 187 copy(root,obj.root); 188 } 189 void copy(BTNode node1,BTNode node2){ 190 if(node2.lChild!=null){//左树递归 191 BTNode l=new BTNode(); 192 l.data=node2.lChild.data;//拷贝左树 193 node1.lChild=l;//左树赋值 194 copy(node1.lChild,node2.lChild); 195 } 196 if(node2.rChild!=null){//右树递归 197 BTNode r=new BTNode(); 198 r.data=node2.rChild.data;//拷贝右树 199 node1.rChild=r;//右树赋值 200 copy(node1.rChild,node2.rChild); 201 } 202 } 203 public void InThreadingFabric(){//中序线索化构造 204 BTNode now=root; 205 InThreading(now); 206 pre.RTag=true;//【最后一个后继为null】 207 pre.rChild=null; 208 } 209 private BTNode pre=null;//前驱指针 210 private void InThreading(BTNode node){//中序线索化递归 211 if(node!=null){//保证节点非空 212 InThreading(node.lChild);//左子树线索化 213 if(node.lChild==null){//如果左子树不存在 214 node.LTag=true;//线索化 215 node.lChild=pre;//前驱 【第一个前驱为null】 216 } 217 if(pre!=null && pre.rChild==null){//后继 218 pre.RTag=true; 219 pre.rChild=node; 220 } 221 pre=node;//保持pre指向node的前驱。 222 InThreading(node.rChild);//左子树线索化 223 } 224 } 225 void InOrderTraversal_Thr(){//线索化遍历 226 BTNode now=root; 227 //遍历前驱 228 while(now.lChild!=null){//要么有左子树。 229 now=now.lChild; 230 } 231 while(now!=null){//要么有左子树。 232 System.out.print(now.data+","); 233 if(now.RTag){now=now.rChild;}//如果是后继,就继续后继。 234 else{ 235 now=now.rChild;//如果不是,则令右子树的最左节点为后继 236 while(!now.LTag) now=now.lChild; 237 } 238 } 239 System.out.println(); 240 } 241 } 242 243 244 class SearchBST extends BTtree{//二叉查找树 245 SearchBST(int[] nums){//由二维数组构造 246 root.data=String.valueOf(nums[0]);//构造根节点 247 for(int i=1;i<nums.length;i++){//对其他元素进行构造 248 BTNode node=new BTNode(); 249 node.data=String.valueOf(nums[i]);//构造叶子节点 250 BTNode parent=root; 251 int nodeV=nums[i]; 252 while(parent!=null){ 253 int parentV=Integer.valueOf(parent.data).intValue();//当前根节点的值 254 if(nodeV<parentV){//左叶子 255 if(parent.lChild==null){//当前根节点的左叶子非空 256 parent.lChild=node;//挂入节点 257 break; //如果这里没有加【break】,就会死循环。待解决☆☆☆ 258 } 259 parent=parent.lChild;//如果这里空了,跳出循环 260 }else{ 261 if(parent.rChild==null){ 262 parent.rChild=node;//挂入节点 263 break; //☆☆☆ 264 } 265 parent=parent.rChild;//如果这里空了,跳出循环 266 } 267 } 268 } 269 } 270 SearchBST(){} 271 }
以上是关于二叉排序树BST的主要内容,如果未能解决你的问题,请参考以下文章