java 二叉查找树 递归_Java实现链式存储的二叉查找树(递归方法)

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 }

/** * 根据等级查询类目 * * @param level * @return */ @Override public List queryCategoryTree(Integer level) { //查询当前级别下类目 List list = categoryDAO.list(level); //组装好的类目,返回前端 List categoryTree = new ArrayList(); //所有类目 List allDTOList = new ArrayList(); if (CollectionUtils.isEmpty(list)) { return categoryTree; } for (CategoryDO categoryDO : list) { allDTOList.add(new CategoryTreeDTO().convertDOToDTO(categoryDO)); } //当前等级类目 categoryTree = allDTOList.stream().filter(dto -> level.equals(dto.getLevel())).collect(Collectors.toList()); for (CategoryTreeDTO categoryTreeDTO : categoryTree) { //组装类目为结构 assembleTree(categoryTreeDTO, allDTOList,Constants.CATEGORY_MAX_LEVEL - level); } return categoryTree; } /** * 组装 * * @param categoryTreeDTO * @param allList * @param remainRecursionCount 剩余递归次数 * @return */ public CategoryTreeDTO assembleTree(CategoryTreeDTO categoryTreeDTO, List allList, int remainRecursionCount) { remainRecursionCount--; //最大递归次数不超过Constants.CATEGORY_MAX_LEVEL-level次,防止坏数据死循环 if(remainRecursionCount < 0){ return categoryTreeDTO; } String categoryCode = categoryTreeDTO.getCategoryCode(); Integer level = categoryTreeDTO.getLevel(); //到达最后等级返回 if (Constants.CATEGORY_MAX_LEVEL == level) { return categoryTreeDTO; } //子类目 List child = allList.stream().filter(a -> categoryCode.equals(a.getParentCode())).collect(Collectors.toList()); if (null == child) { return categoryTreeDTO; } categoryTreeDTO.setChildren(child); //组装子类目 for (CategoryTreeDTO dto : child) { assembleTree(dto, allList,remainRecursionCount); } return categoryTreeDTO; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值