代码改变世界

二叉树的基本操作

2012-07-09 17:06  coodoing  阅读(280)  评论(0)    收藏  举报

   主要利用java实现了二叉树的一些基本操作:

  1. 获取树的深度;
  2. 添加、删除节点
  3. 获取左右兄弟节点
  4. 简单的递归中序遍历。。后续会提供前序,后序遍历的方法以及非递归遍历的方法
BinaryTree
  1 package Tree;
  2 
  3 class BTNode {
  4     int data;
  5     BTNode left;
  6     BTNode right;
  7 
  8     public BTNode(int data) {
  9         this(data, null, null);
 10     }
 11 
 12     public BTNode(int data, BTNode left, BTNode right) {
 13         this.data = data;
 14         this.left = left;
 15         this.right = right;
 16     }
 17 }
 18 
 19 class BinaryTree {
 20     BTNode root;
 21 
 22     /**
 23      * 创建一个空的二叉树
 24      */
 25     public void initBiTree() {
 26         root = null;// new BTNode<T>(null);
 27     }
 28 
 29     /**
 30      * 利用数组输入构建二叉树
 31      * 
 32      * @param data
 33      *            要输入的数值
 34      */
 35     public void buildTree(int[] data) {
 36         root = new BTNode(data[0]);
 37         for (int i = 1; i < data.length; i++) {
 38             BTNode tmpNode = root;//new BTNode(data[i]);
 39             while (true) {
 40                 if (tmpNode.data == data[i])
 41                     break;
 42                 if (tmpNode.data > data[i]) {// 小于等于根节点
 43                     if (tmpNode.left == null) {// 如果左孩子为空,这把当前数组元素插入到左孩子节点的位置
 44                         tmpNode.left = new BTNode(data[i]);
 45                         break;
 46                     }
 47                     tmpNode = tmpNode.left;// 如果不为空的话,则把左孩子节点用来和当前数组元素作比较
 48                 } else { // 大于根节点
 49                     if (tmpNode.right == null) {// 如果右孩子为空,这把当前数组元素插入到左孩子节点的位置
 50                         tmpNode.right = new BTNode(data[i]);
 51                         break;
 52                     }
 53                     tmpNode = tmpNode.right;// 如果不为空的话,则把右孩子节点用来和当前数组元素作比较
 54                 }
 55             }
 56         }
 57     }
 58 
 59     // 清空二叉树
 60     public void destroyBiTree() {
 61         destroyBiTree(root);
 62     }
 63 
 64     private void destroyBiTree(BTNode root) {
 65         while (root != null) {
 66             destroyBiTree(root.left);
 67             destroyBiTree(root.right);
 68         }
 69     }
 70 
 71     // 将二叉树清为空树
 72     public void clearBiTree() {
 73         if (root == null)
 74             return;
 75         root = null;
 76     }
 77 
 78     // 查找二叉查找树的最小节点
 79     public BTNode getMinNode(BTNode node) {
 80         while (node.left != null) {
 81             node = node.left;
 82         }
 83         return node;
 84     }
 85 
 86     // 查找二叉查找树的最大节点
 87     public BTNode getMaxNode(BTNode node) {
 88         while (node.right != null) {
 89             node = node.right;
 90         }
 91         return node;
 92     }
 93 
 94     // 查找节点的前驱节点
 95     public BTNode getPredecessor(BTNode node) {
 96         if (node.left != null) {
 97             return getMaxNode(node.left);// 左子树的最大值
 98         }
 99         BTNode parent = getParent(node);
100         //System.out.println("K的父节点(k的data为54):" + y.data);
101         while (parent != null && node == parent.left) {// 向上找到最近的一个节点,其父亲节点的右子树包涵了当前节点或者其父亲节点为空
102             node = parent;
103             parent = getParent(parent);
104         }
105         return parent;
106     }
107 
108     // 查找节点的后继节点
109     public BTNode getSuccessor(BTNode node) {
110         if (node.right != null) {
111             return getMinNode(node.right);// 右子树的最小值
112         }
113         //为了避免54,87,43的情况
114         BTNode parent = getParent(node);
115         //System.out.println("K的父节点(k的data为54):" + y.data);        
116         if (parent == null)
117             return null;
118         while (parent != null) {
119             if (parent.left == node) {
120                 return parent; //为左子树情况,后继为父节点
121             } else {
122                 node = parent; //否则递归
123                 parent = getParent(parent);
124             }
125         }
126         return parent;
127     }
128 
129     // 求出父亲节点,在定义节点类BSTreeNode的时候,没有申明父亲节点,所以这里专门用parent用来输出父亲节点(主要是不想修改代码了,就在这里加一个parent函数吧)
130     public BTNode getParent(BTNode node) {
131         BTNode p = root;
132         BTNode tmp = null;
133         while (p != null && p.data != node.data) {// 最后的p为p.data等于k.data的节点,tmp为p的父亲节点
134             if (p.data > node.data) {
135                 tmp = p;// 临时存放父亲节点
136                 p = p.left;
137             } else {
138                 tmp = p;// 临时存放父亲节点
139                 p = p.right;
140             }
141         }
142         return tmp;
143     }
144 
145     //返回root根节点
146     public BTNode getRootNode() {
147         return root;
148     }
149 
150     public int getDepth() {
151         int depth = 0;
152         depth = getRecDepth(root);
153         return depth;
154     }
155 
156     private int getRecDepth(BTNode node) {
157         if (node == null) {
158             return 0;
159         }
160         //没有子树  
161         if (node.left == null && node.right == null) {
162             return 1;
163         } else {
164             int leftDeep = getRecDepth(node.left);
165             int rightDeep = getRecDepth(node.right);
166             //记录其所有左、右子树中较大的深度  
167             int max = leftDeep > rightDeep ? leftDeep : rightDeep;
168             //返回其左右子树中较大的深度 + 1  
169             return max + 1;
170         }
171     }
172 
173     //或者直接放入到BTNode的属性当中去
174     public int getNodeValue(BTNode node) {
175         return node!=null?node.data:-1;
176     }
177 
178     public BTNode getLeftChild(BTNode node) {
179         return node!=null?node.left:null;
180     }
181 
182     public BTNode getRightChild(BTNode node) {
183         return node!=null?node.right:null;
184     }
185 
186     public BTNode getLeftSibling(BTNode node) {
187         BTNode parent = getParent(node);
188         //node为左孩子或者无左兄弟节点
189         if(parent.data>node.data||parent.left == null)
190             return null;
191         return parent.left;
192     }
193 
194     public BTNode getRightSibling(BTNode node) {
195         BTNode parent = getParent(node);
196         //node为右孩子或者无右兄弟节点右边
197         if(parent.data<node.data||parent.right == null)
198             return null;
199         return parent.right;
200     }
201 
202     public boolean existNode(BTNode p, int data) {
203         if (!isEmpty()) {
204             while (p != null) {
205                 if (p.data == data)
206                     return true;
207                 if (p.data > data)
208                     return existNode(p.left, data);
209                 else
210                     return existNode(p.right, data);
211             }
212         }
213         return false;
214     }
215 
216     public BTNode getExsitNode(int data) {
217         if (existNode(root, data)) {
218             return getExsitNode(root, data);
219         }
220         return null;
221     }
222 
223     private BTNode getExsitNode(BTNode p, int data) {
224         if (p.data == data)
225             return p;
226         if (p.data > data)
227             return getExsitNode(p.left, data);
228         else
229             return getExsitNode(p.right, data);
230     }
231 
232     public boolean isEmpty() {
233         return (root == null);
234     }
235 
236     //与二叉查找树的删除有些区别
237     public boolean deleteChild(BTNode node) {
238         BTNode p = root;
239         boolean exsits = existNode(root, node.data);
240         if (exsits && p != null) {
241             //deleteRecChild(node);
242             BTNode parent = getParent(node);
243             if (parent.data > node.data)//即node为左节点
244             {
245                 parent.left = null;
246             } else {
247                 parent.right = null;
248             }
249         }
250         return false;
251     }
252 
253     //递归删除node对应的子树
254     public void deleteRecChild(BTNode node) {
255         BTNode parent = getParent(node);
256         System.out.println("parentData=" + parent.data);
257         if (node.left != null || node.right != null) {
258             //递归出现问题
259             deleteRecChild(node.left);
260             deleteRecChild(node.right);
261         } else {
262             if (parent.data > node.data)//即node为左节点
263             {
264                 parent.left = null;
265             } else {
266                 parent.right = null;
267             }
268         }
269     }
270 
271     //插入指定的node节点
272     public void insertChild(BTNode node) {
273         BTNode p = root;
274         while (true) {
275             if (p.data == node.data)
276                 return;
277             else if (p.data > node.data) {
278                 if (p.left == null) {
279                     p.left = node;
280                     break;
281                 }
282                 p = p.left;
283             } else {
284                 if (p.right == null) {
285                     p.right = node;
286                     break;
287                 }
288                 p = p.right;
289             }
290         }
291     }
292 
293     //插入data
294     public void insertNode(int data) {
295 
296     }
297 
298     // 批量插入节点
299     public void insertChild(int[] data) {
300 
301     }
302 
303     /**
304      * 递归打印出二叉树
305      */
306     public void traversalBiTree() {
307         traversalBiTree(root);
308         System.out.println();
309     }
310 
311     /**
312      * 从根结点开始遍历,从树的最高层叶子结点开始输出,从左至右
313      * 
314      * @param node
315      *            当前的结点
316      */
317     private void traversalBiTree(BTNode node) {
318         if (node != null) {
319             traversalBiTree(node.left);
320             System.out.print(node.data + "  ");
321             traversalBiTree(node.right);
322         }
323     }
324 }
325 
326 public class BinaryTreeTest {
327     public static void main(String[] args) {
328         Integer a = new Integer(6);
329         Integer b = new Integer(7);
330         Integer c = new Integer(8);
331         System.out.println(c.compareTo(b) + "   " + a);
332 
333         BinaryTree biTree = new BinaryTree();
334 
335         /************************
336          * 构造的二叉树结构为:
337          *         2
338          *        / \
339          *       1   8
340          *             / \
341          *            7   9
342          *           /
343          *       4
344          *      / \
345          *     3   6
346          *        /
347          *       5
348          * **********************/
349 
350         /************************
351          * 初始化操作
352          * **********************/
353         int[] data = { 2, 8, 7, 4, 9, 3, 1, 6, 7, 5 };
354         biTree.buildTree(data);
355         System.out.println("二叉树的深度为:" + biTree.getDepth());
356         System.out.println("初始化后,二叉树遍历结果:");
357         biTree.traversalBiTree();
358         BTNode p = biTree.root;
359         System.out.println("根节点相关信息:" + p.right.right.data + "   "
360                 + p.right.left.data);
361 
362         /************************
363          * 插入子节点操作
364          * **********************/
365         BTNode node = new BTNode(10);
366         biTree.insertChild(node);
367         System.out.println("插入子节点后,二叉树遍历结果:");
368         biTree.traversalBiTree();
369 
370         node = new BTNode(7);
371         boolean result;
372         result = biTree.existNode(biTree.root, node.data);
373         System.out.println(result == true ? "Node存在" : "Node不存在");
374 
375         /************************
376          * 递归删除子树操作
377          * **********************/
378         node = biTree.getExsitNode(7);
379         System.out.println("左右孩子节点分别为:"+biTree.getNodeValue(node.left)+"   "+biTree.getNodeValue(node.right));
380         System.out.println("节点的左右兄弟节点分别为:"+biTree.getLeftSibling(node)+"   "+biTree.getRightSibling(node));
381         
382         biTree.deleteChild(node);
383         System.out.println("递归删除子树后,二叉树遍历结果:");
384         biTree.traversalBiTree();
385 
386         /************************
387          * 清空操作
388          * **********************/
389         //biTree.clearBiTree();
390         //biTree.traversalBiTree();
391     }
392 }