二叉排序树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的主要内容,如果未能解决你的问题,请参考以下文章

数据结构与算法:树 二叉排序树(BST)

二叉排序树(BST)的建立

二叉排序树(BST)

(王道408考研数据结构)第五章树-第四节1:二叉树排序树(BST)及其操作

二叉排序树BST

树和二叉树总结—BST二叉排序树