数据结构-二叉搜索树Java实现

1,Node.java

生成基础二叉树的结构

 1 package com.cnblogs.mufasa.searchTree;
 2 
 3 /**
 4  * 节点配置父+左+右
 5  */
 6 public class Node{
 7     Node parent;
 8     Node leftChild;
 9     Node rightChild;
10     int val;
11     public Node(Node parent, Node leftChild, Node rightChild,int val) {
12         super();
13         this.parent = parent;
14         this.leftChild = leftChild;
15         this.rightChild = rightChild;
16         this.val = val;
17     }
18 
19     public Node(int val){
20         this(null,null,null,val);
21     }
22 
23     public Node(Node node,int val){
24         this(node,null,null,val);
25     }
26 }
View Code

图1 Node.java结构

 

2,SearchBinaryTree.java

在原有二叉树的结构上,进行搜索二叉树的功能扩充:

①数据增加:递归版本插入、迭代版本

②数据删除:

③数据查找:

④数据遍历:前中后

  1 package com.cnblogs.mufasa.searchTree;
  2 
  3 
  4 
  5 public class SearchBinaryTree {
  6 
  7     private Node root;
  8     private int size;
  9     public SearchBinaryTree() {
 10         super();
 11     }
 12 
 13     /**
 14      * 增加节点
 15      * @param val
 16      * @return
 17      */
 18     public boolean add(int val) {
 19         if(root == null){//初始节点为空
 20             root = new Node(val);
 21             size++;
 22             return true;
 23         }
 24         //初始节点不为空
 25         Node node = getAdapterNode(root, val);
 26         Node newNode = new Node(val);
 27         if(node.val > val){
 28             node.leftChild = newNode;
 29             newNode.parent = node;
 30         }else if(node.val < val){
 31             node.rightChild = newNode;
 32             newNode.parent = node;
 33         }else{
 34             return false;//增加数据和搜索二叉树中原有数据相同不符合基本限定条件
 35         }
 36         size++;
 37         return true;
 38     }
 39 
 40     /**
 41      * 获取最合适的插入节点
 42      * @param node
 43      * @param val
 44      * @return
 45      */
 46     private Node getAdapterNode(Node node,int val){
 47         //该节点为空
 48         if(node == null){
 49             return node;
 50         }
 51 
 52         // 往左子树中插入,但没左子树,则返回
 53         if(node.val > val && node.leftChild == null){
 54             return node;
 55         }
 56 
 57         // 往右子树中插入,但没右子树,也返回
 58         if(node.val < val && node.rightChild == null){
 59             return node;
 60         }
 61 
 62         // 该节点是叶子节点,则返回
 63         if(node.leftChild == null && node.rightChild == null){
 64             return node;
 65         }
 66 
 67         //节点可以继续向下,直接递归调用
 68         if(node.val > val && node.leftChild != null){
 69             return getAdapterNode(node.leftChild, val);
 70         }else if(node.val < val && node.rightChild != null){
 71             return getAdapterNode(node.rightChild, val);
 72         }else{
 73             return node;
 74         }
 75     }
 76 
 77     /**
 78      * 进行迭代增加元素
 79      * @param val
 80      * @return
 81      */
 82     public boolean put(int val){
 83         return putVal(root,val);
 84     }
 85 
 86     /**
 87      *直接循环搜索目标节点进行数据增加
 88      * @param node
 89      * @param val
 90      * @return
 91      */
 92     private boolean putVal(Node node,int val){
 93         if(node == null){// 初始化根节点
 94             node = new Node(val);
 95             root = node;
 96             size++;
 97             return true;
 98         }
 99         //节点非空
100         Node temp = node;
101         Node p;
102         int t;
103         /**
104          * 通过do while循环迭代获取最佳节点,
105          */
106         do{
107             p = temp;
108             t = temp.val-val;
109             if(t > 0){
110                 temp = temp.leftChild;
111             }else if(t < 0){
112                 temp = temp.rightChild;
113             }else{
114                 temp.val = val;//增加数据和搜索二叉树中原有数据相同不符合基本限定条件
115                 return false;
116             }
117         }while(temp != null);
118 
119         Node newNode = new Node(p, val);
120         if(t > 0){
121             p.leftChild = newNode;
122         }else if(t < 0){
123             p.rightChild = newNode;
124         }
125         size++;
126         return true;
127     }
128 
129     /**
130      * 节点删除
131      * @param val
132      * @return
133      */
134     public boolean delete(int val){
135         Node node = getNode(val);
136         if(node == null){//没有该节点
137             return false;
138         }
139         Node parent = node.parent;
140         Node leftChild = node.leftChild;
141         Node rightChild = node.rightChild;
142 
143         //以下所有子节点为空的情况,则表明删除的节点是【叶节点】
144         if(leftChild == null && rightChild == null){//没有子节点
145             if(parent != null){
146                 if(parent.leftChild == node){
147                     parent.leftChild = null;
148                 }else if(parent.rightChild == node){
149                     parent.rightChild = null;
150                 }
151             }else{//不存在父节点,则表明删除节点为【根节点】,直接返回空
152                 root = null;
153             }
154             node = null;
155             return true;
156 
157         }else if(leftChild == null && rightChild != null){// 只有右节点
158             if(parent != null && parent.val > val){// 存在父节点,且node位置为父节点的左边
159                 parent.leftChild = rightChild;
160             }else if(parent != null && parent.val < val){// 存在父节点,且node位置为父节点的右边
161                 parent.rightChild = rightChild;
162             }else{//父节点不存在!!!
163                 root = rightChild;
164             }
165             node = null;
166             return true;
167 
168         }else if(leftChild != null && rightChild == null){// 只有左节点
169             if(parent != null && parent.val > val){// 存在父节点,且node位置为父节点的左边
170                 parent.leftChild = leftChild;
171             }else if(parent != null && parent.val < val){// 存在父节点,且node位置为父节点的右边
172                 parent.rightChild = leftChild;
173             }else{//父节点不存在!!!
174                 root = leftChild;
175             }
176             node = null;
177             return true;
178 
179         }else if(leftChild != null && rightChild != null){// 两个子节点都存在,相当于直接替换节点
180             Node successor = getSuccessor(node);// 这种情况,一定存在后继节点
181             int temp = successor.val;
182             boolean delete = delete(temp);
183             if(delete){
184                 node.val = temp;
185             }
186             successor = null;
187             return true;
188         }
189         return false;
190     }
191 
192     /**
193      *
194      * @param node
195      * @return
196      */
197     private Node getSuccessor(Node node){
198         if(node.rightChild != null){//肯定不为空
199             Node rightChild = node.rightChild;
200             while(rightChild.leftChild != null){//不断的向左转向搜索数值
201                 rightChild = rightChild.leftChild;
202             }
203             return rightChild;
204         }
205         //右节点为空这个不存在啊!!!
206         Node parent = node.parent;
207         while(parent != null && (node == parent.rightChild)){
208             node = parent;
209             parent = parent.parent;
210         }
211         return parent;
212     }
213 
214 
215     /**
216      * 搜索节点
217      * @param val
218      * @return
219      */
220     public Node getNode(int val){
221         Node temp = root;
222         int t;
223         do{//直接使用循环遍历的方法
224             t = temp.val-val;
225             if(t > 0){
226                 temp = temp.leftChild;
227             }else if(t < 0){
228                 temp = temp.rightChild;
229             }else{
230                 return temp;
231             }
232         }while(temp != null);
233         return null;
234     }
235 
236     /**
237      * 节点删除
238      * @param val
239      * @return
240      */
241     public boolean remove(int val){
242         Node node = getNode(val);
243         if(node == null){
244             return false;
245         }
246 
247         if(node.leftChild == null){// 1、左节点不存在,右节点可能存在,包含两种情况  ,两个节点都不存在和只存在右节点
248             transplant(node, node.rightChild);
249         }else if(node.rightChild == null){//2、左孩子存在,右节点不存在
250             transplant(node, node.leftChild);
251         }else{// 3、两个节点都存在
252             Node successor = getSuccessor(node);// 得到node后继节点
253             if(successor.parent != node){// 后继节点存在node的右子树中。
254                 transplant(successor, successor.rightChild);// 用后继节点的右子节点替换该后继节点
255                 successor.rightChild = node.rightChild;// 将node节点的右子树赋给后继节点的右节点,即类似后继与node节点调换位置
256                 successor.rightChild.parent = successor;// 接着上一步  给接过来的右节点的父引用复制
257             }
258             transplant(node, successor);
259             successor.leftChild = node.leftChild;
260             successor.leftChild.parent = successor;
261         }
262         return true;
263     }
264     /**
265      * 将child节点替换node节点
266      * @param node    要删除的节点
267      * @param child   node节点的子节点
268      */
269     private void transplant(Node node,Node child){
270         /**
271          * 1、先判断 node是否存在父节点
272          *    1、不存在,则child替换为根节点
273          *    2、存在,则继续下一步
274          * 2、判断node节点是父节点的那个孩子(即判断出 node是右节点还是左节点),
275          *    得出结果后,将child节点替换node节点 ,即若node节点是左节点 则child替换后 也为左节点,否则为右节点
276          * 3、将node节点的父节点置为child节点的父节点
277          */
278 
279         if(node.parent == null){
280             this.root = child;
281         }else if(node.parent.leftChild == node){
282             node.parent.leftChild = child;
283         }else if(node.parent.rightChild == node){
284             node.parent.rightChild = child;
285         }
286         if(child != null){
287             child.parent = node.parent;
288         }
289     }
290 
291     public void print(int type){//方法的重载
292         if(type==0){//前序
293             printPre(root);
294         }else if(type==1){
295             printMid(root);
296         }else if(type==2){
297             printEnd(root);
298         }
299     }
300 
301     private void printPre(Node root){//前序遍历
302         if(root != null){
303             System.out.println(root.val);// 位置在中间,则中序,若在前面,则为先序,否则为后续
304             printPre(root.leftChild);
305             printPre(root.rightChild);
306         }
307     }
308 
309     private void printMid(Node root){//中序遍历
310         if(root != null){
311             printMid(root.leftChild);
312             System.out.println(root.val);// 位置在中间,则中序,若在前面,则为先序,否则为后续
313             printMid(root.rightChild);
314         }
315     }
316 
317     private void printEnd(Node root){//后序遍历
318         if(root != null){
319             printEnd(root.leftChild);
320             printEnd(root.rightChild);
321             System.out.println(root.val);// 位置在中间,则中序,若在前面,则为先序,否则为后续
322         }
323     }
324 
325 }
View Code

 

图2 SearchBinaryTree.java结构

 

3,JavaDemo.java

 1 package com.cnblogs.mufasa.searchTree;
 2 
 3 public class JavaDemo {
 4     public static void main(String[] args) {
 5         SearchBinaryTree tree=new SearchBinaryTree();
 6         tree.add(5);
 7         tree.add(1);
 8         tree.add(100);
 9         tree.add(50);
10         tree.add(22);
11         tree.add(48);
12         tree.print(2);
13     }
14 }
View Code

 

4,特别鸣谢

https://www.cnblogs.com/qm-article/p/9279655.html

posted on 2019-08-03 11:10  周健康  阅读(268)  评论(0编辑  收藏  举报

导航