1 importjava.lang.Integer;2 importjava.util.LinkedList;3 importjava.util.Queue;4 importjava.util.Scanner;5
6 /*
7 * 二叉排序树(二叉查找树)的实现8 */
9 public classBinarySearchTree {10 private TreeNode root; //根节点
11
12 publicBinarySearchTree(){13 root = null;14 }15
16 //用一个数组去构建二叉查找树
17 public TreeNodebuildBST(Integer[] array){18 if(array.length == 0){19 return null;20 }else{21 root = null; //初始化树为空树
22 for(int i=0; i
23 root =insertNode(root,array[i]);24 }25 returnroot;26 }27 }28
29 //在二叉查找树中插入一个数据域为data的结点,新插入的结点一定是某个叶子节点
30 public TreeNode insertNode(TreeNodenode, Integer data){31 if(node == null){ //原树为空,新插入的记录为根节点
32 node = new TreeNode(data,null,null);33 }else{34 if(node.getData() == data){ //树中存在相同关键字的结点,什么也不做
35
36 }else{37 if(node.getData() > data){ //根节点>插入数据,插入到左子树中
38 node.setLchild(insertNode(node.getLchild(),data));39 }else{ //根节点
40 node.setRchild(insertNode(node.getRchild(),data));41 }42 }43 }44 returnnode;45 }46
47 //二叉查找树的中序遍历,可以得到一个递增的有序数列
48 public void inOrder(TreeNodenode){49 if(node != null){50 inOrder(node.getLchild());51 System.out.print(node.getData()+" ");52 inOrder(node.getRchild());53 }54 }55 //二叉查找树的层次遍历
56 public void levelOrder(TreeNoderoot){57 Queue> nodeQueue = new LinkedList>();58 TreeNode node = null;59 nodeQueue.add(root); //将根节点入队
60 while(!nodeQueue.isEmpty()){ //队列不空循环
61 node =nodeQueue.peek();62 System.out.print(node.getData()+" ");63 nodeQueue.poll(); //队头元素出队
64 if(node.getLchild() != null){ //左子树不空,则左子树入队列
65 nodeQueue.add(node.getLchild());66 }67 if(node.getRchild() != null){ //右子树不空,则右子树入队列
68 nodeQueue.add(node.getRchild());69 }70 }71 }72
73 //查找数据域为data的结点,若不存在,返回null
74 public TreeNode searchNode(TreeNodenode, Integer data){75 while(node != null && node.getData() !=data){76 if(node.getData() >data){77 node = node.getLchild(); //根节点>数据,向左走
78 }else{79 node = node.getRchild(); //根节点
80 }81 }82 returnnode;83 }84
85 //查找最大值:不断地寻找右子节点
86 public TreeNode getMaxData(TreeNodenode){87 if(node.getRchild() == null){88 returnnode;89 }else{90 returngetMaxData(node.getRchild());91 }92 }93
94 //查找最小值:不断地寻找左子节点
95 public TreeNode getMinData(TreeNodenode){96 if(node.getLchild() == null){97 returnnode;98 }else{99 returngetMinData(node.getLchild());100 }101 }102
103 //得到数据域为data的结点的直接父节点parentNode
104 public TreeNode getParentNode(TreeNoderoot, Integer data){105 TreeNode parentNode =root;106 if(parentNode.getData() == data){ //根节点的父节点返回为null
107 return null;108 }109 while(parentNode != null){110 //查找当前节点的父节点的左右子节点,若是相等,则返回该父节点
111 if((parentNode.getLchild() != null && parentNode.getLchild().getData() == data) ||
112 (parentNode.getRchild() != null && parentNode.getRchild().getData() ==data)){113 returnparentNode;114 }else{115 if(parentNode.getData() > data){ //向左查找父节点
116 parentNode =parentNode.getLchild();117 }else{118 parentNode = parentNode.getRchild(); //向右查找父节点
119 }120 }121 }122 return null;123 }124
125 /**
126 * 得到结点node的直接前趋127 * a.该节点左子树不为空:其前驱节点为其左子树的最大元素128 * b.该节点左子树为空: 其前驱节点为其祖先节点(递归),且该祖先节点的右孩子也为其祖先节点129 * (就是一直往其parent找,出现左拐后的那个祖先节点)130 */
131 public TreeNode getPrecessor(TreeNode root,TreeNodenode){132 if(node == null){133 return null;134 }135 //a.该节点左子树不为空:其前驱节点为其左子树的最大元素
136 if(node.getLchild() != null){137 returngetMaxData(node.getLchild());138 }else{ //b.该节点左子树为空: 其前驱节点为其祖先节点(递归)
139 TreeNode parentNode =getParentNode(root, node.getData());140 while(parentNode != null && node ==parentNode.getLchild()){141 node =parentNode;142 parentNode =getParentNode(root, parentNode.getData());143 }144 returnparentNode;145 }146 }147
148 /**
149 * 得到结点node的直接后继(后继节点就是比要删除的节点的关键值要大的节点集合中的最小值)150 * a.该节点右子树不为空,其后继节点为其右子树的最小元素151 * b.该节点右子树为空,则其后继节点为其祖先节点(递归),且此祖先节点的左孩子也是该节点的祖先节点,152 * 就是说一直往上找其祖先节点,直到出现右拐后的那个祖先节点:153 */
154 public TreeNode getSuccessor(TreeNode root,TreeNodenode){155 if(node == null){156 return null;157 }158 //a.该节点右子树不为空,其后继节点为其右子树的最小元素
159 if(node.getRchild() != null){160 returngetMinData(node.getRchild());161 }else{ //b.该节点右子树为空,则其后继节点为其最高祖先节点(递归)
162 TreeNode parentNode =getParentNode(root, node.getData());163 while(parentNode != null && node ==parentNode.getRchild()){164 node =parentNode;165 parentNode =getParentNode(root, parentNode.getData());166 }167 returnparentNode;168 }169 }170
171 /**
172 * 删除数据域为data的结点173 * 按三种情况处理:174 * a.如果被删除结点z是叶子节点,则直接删除,不会破坏二叉查找树的性质175 * b.如果节点z只有一颗左子树或右子树,则让z的子树成为z父节点的子树,代替z的位置176 * c.若结点z有左、右两颗子树,则令z的直接后继(或直接前驱)替代z,177 * 然后从二叉查找树中删去这个直接后继(或直接前驱),这样就转换为第一或第二种情况178 *@paramnode 二叉查找树的根节点179 *@paramdata 需要删除的结点的数据域180 *@return
181 */
182 public boolean deleteNode(TreeNodenode, Integer data){183 if(node == null){ //树为空
184 throw new RuntimeException("树为空!");185 }186 TreeNode delNode= searchNode(node, data); //搜索需要删除的结点
187 TreeNode parent = null;188 if(delNode == null){ //如果树中不存在要删除的关键字
189 throw new RuntimeException("树中不存在要删除的关键字!");190 }else{191 parent = getParentNode(node,data); //得到删除节点的直接父节点192 //a.如果被删除结点z是叶子节点,则直接删除,不会破坏二叉查找树的性质
193 if(delNode.getLchild()==null && delNode.getRchild()==null){194 if(delNode==parent.getLchild()){ //被删除节点为其父节点的左孩子
195 parent.setLchild(null);196 }else{ //被删除节点为其父节点的右孩子
197 parent.setRchild(null);198 }199 return true;200 }201 //b1.如果节点z只有一颗左子树,则让z的子树成为z父节点的子树,代替z的位置
202 if(delNode.getLchild()!=null && delNode.getRchild()==null){203 if(delNode==parent.getLchild()){ //被删除节点为其父节点的左孩子
204 parent.setLchild(delNode.getLchild());205 }else{ //被删除节点为其父节点的右孩子
206 parent.setRchild(delNode.getLchild());207 }208 delNode.setLchild(null); //设置被删除结点的左孩子为null
209 return true;210 }211 //b2.如果节点z只有一颗右子树,则让z的子树成为z父节点的子树,代替z的位置
212 if(delNode.getLchild()==null && delNode.getRchild()!=null){213 if(delNode==parent.getLchild()){ //被删除节点为其父节点的左孩子
214 parent.setLchild(delNode.getRchild());215 }else{ //被删除节点为其父节点的右孩子
216 parent.setRchild(delNode.getRchild());217 }218 delNode.setRchild(null); //设置被删除结点的右孩子为null
219 return true;220 }221 //c.若结点z有左、右两颗子树,则删除该结点的后继结点,并用该后继结点取代该结点
222 if(delNode.getLchild()!=null && delNode.getRchild()!=null){223 TreeNode successorNode = getSuccessor(node,delNode); //得到被删除结点的后继节点
224 deleteNode(node,successorNode.getData()); //删除该结点的后继结点
225 delNode.setData(successorNode.getData()); //用该后继结点取代该结点
226 return true;227 }228 }229 return false;230 }231
232
233 public static voidmain(String args[]){234 Scanner input = newScanner(System.in);235 Integer[] array = {8,3,10,1,6,14,4,7,13};236 BinarySearchTree bst = newBinarySearchTree();237 TreeNode root =bst.buildBST(array);238 System.out.print("层次遍历:");239 bst.levelOrder(root);240 System.out.print("\n"+"中序遍历:");241 bst.inOrder(root);242 System.out.println();243 System.out.print("得到最大值:");244 System.out.println(bst.getMaxData(root).getData());245 System.out.print("得到最小值:");246 System.out.println(bst.getMinData(root).getData());247 System.out.print("向二叉查找树中插入一个节点,请输入需插入节点的数据域:");248 int data =input.nextInt();249 System.out.print("插入节点"+ data +"后,中序遍历的结果:");250 root =bst.insertNode(root, data);251 bst.inOrder(root);252 System.out.println("\n"+"在二叉查找树中查找元素,"+"请输入需要查找的结点值:");253 data =input.nextInt();254 if(bst.searchNode(root, data) == null){255 System.out.println("false");256 }else{257 System.out.println("true");258 }259 System.out.println("查找节点的直接父节点,"+"请输入需要查找的结点值:");260 data =input.nextInt();261 System.out.print("节点"+ data +"的父节点是:");262 if(bst.getParentNode(root, data) == null){263 System.out.println("null");264 }else{265 System.out.println(bst.getParentNode(root, data).getData());266 }267 System.out.println("删除结点,"+"请输入需要删除的结点值:");268 data =input.nextInt();269 if(bst.deleteNode(root, data)){270 System.out.print("删除结点后的层次遍历:");271 bst.levelOrder(root);272 System.out.print("\n"+"删除结点后的中序遍历:");273 bst.inOrder(root);274 }275 }276 }