二叉排序树 java_二叉查找树的java实现

这段代码实现了一个泛型二叉查找树(BST),包括插入、查找、删除、获取最大值、最小值、按排名选择节点、向上取整、向下取整等操作。树的节点包含键、值、子节点链接和子树节点总数。删除操作处理了节点可能有的不同子树情况。
摘要由CSDN通过智能技术生成

1 package查找;2

3 importjava.util.ArrayList;4 importjava.util.List;5

6 public class BST, Value>{7 private classNode {8 private Key key; //键

9 private Value value;//值

10 private Node left, right; //指向子树的链接

11 private int n; //以该节点为根的子树中的节点总数

12

13 public Node(Key key, Value val, intn) {14 this.key =key;15 this.value =val;16 this.n =n;17 }18 }19

20 privateNode root;21

22 public intsize() {23 returnsize(root);24 }25

26 private intsize(Node x) {27 if (x == null)28 return 0;29 else

30 returnx.n;31 }32

33 /**

34 * 如果树是空的,则查找未命中 如果被查找的键小于根节点,则在左子树中继续查找 如果被查找的键大于根节点,则在右子树中继续查找35 * 如果被查找的键和根节点的键相等,查找命中36 *37 *@paramkey38 *@return

39 */

40 publicValue get(Key key) {41 returnget(root, key);42 }43

44 privateValue get(Node x, Key key) {45 if (x == null)46 return null;47 int cmp =key.compareTo(x.key);48 if (cmp < 0)49 returnget(x.left, key);50 else if (cmp > 0)51 returnget(x.right, key);52 else

53 returnx.value;54 }55

56 /**

57 * 二叉查找树的一个很重要的特性就是插入的实现难度和查找差不多。58 * 当查找到一个不存在与树中的节点(null)时,new 新节点,并将上一路径指向该节点59 *60 *@paramkey61 *@paramval62 */

63 public voidput(Key key, Value val) {64 root =put(root, key, val);65 }66

67 privateNode put(Node x, Key key, Value val) {68 if (x == null)69 return new Node(key, val, 1);70 int cmp =key.compareTo(x.key);71 if (cmp < 0)72 x.left =put(x.left, key, val);73 else if (cmp > 0)74 x.right =put(x.right, key, val);75 else

76 x.value =val;77 x.n = 1 + size(x.left) + size(x.right); //要及时更新节点的子树数量

78 returnx;79 }80

81 publicKey min() {82 returnmin(root).key;83 }84

85 privateNode min(Node x) {86 if (x.left == null)87 returnx;88 returnmin(x.left);89 }90

91 publicKey max() {92 returnmax(root).key;93 }94

95 privateNode max(Node x) {96 if (x.right == null)97 returnx;98 returnmax(x.right);99 }100

101 /**

102 * 向下取整:找出小于等于该键的最大键103 *104 *@paramkey105 *@return

106 */

107 publicKey floor(Key key) {108 Node x =floor(root, key);109 if (x == null)110 return null;111 else

112 returnx.key;113 }114

115 /**

116 * 如果给定的键key小于二叉查找树的根节点的键,那么小于等于key的最大键一定出现在根节点的左子树中117 * 如果给定的键key大于二叉查找树的根节点,那么只有当根节点右子树中存在大于等于key的节点时,118 * 小于等于key的最大键才会出现在右子树中,否则根节点就是小于等于key的最大键119 *120 *@paramx121 *@paramkey122 *@return

123 */

124 privateNode floor(Node x, Key key) {125 if (x == null)126 return null;127 int cmp =key.compareTo(x.key);128 if (cmp == 0)129 returnx;130 else if (cmp < 0)131 returnfloor(x.left, key);132 else{133 Node t =floor(x.right, key);134 if (t == null)135 returnx;136 else

137 returnt;138 }139 }140

141 /**

142 * 向上取整:找出大于等于该键的最小键143 *144 *@paramkey145 *@return

146 */

147 publicKey ceiling(Key key) {148 Node x =ceiling(root, key);149 if (x == null)150 return null;151 else

152 returnx.key;153 }154

155 /**

156 * 如果给定的键key大于二叉查找树的根节点的键,那么大于等于key的最小键一定出现在根节点的右子树中157 * 如果给定的键key小于二叉查找树的根节点,那么只有当根节点左子树中存在大于等于key的节点时,158 * 大于等于key的最小键才会出现在左子树中,否则根节点就是大于等于key的最小键159 *160 *@paramx161 *@paramkey162 *@return

163 */

164 privateNode ceiling(Node x, Key key) {165 if (x == null)166 return null;167 int cmp =key.compareTo(x.key);168 if (cmp == 0)169 returnx;170 else if (cmp > 0) {171 returnceiling(x.right, key);172 } else{173 Node t =floor(x.left, key);174 if (t == null)175 returnx;176 else

177 returnt;178 }179 }180

181 /**

182 * 选择排名为k的节点183 *184 *@paramk185 *@return

186 */

187 public Key select(intk) {188 returnselect(root, k).key;189 }190

191 private Node select(Node x, intk) {192 if (x == null)193 return null;194 int t =size(x.left);195 if (t >k)196 returnselect(x.left, k);197 else if (t

199 else

200 returnx;201 }202

203 /**

204 * 查找给定键值的排名205 *206 *@paramkey207 *@return

208 */

209 public intrank(Key key) {210 returnrank(key, root);211 }212

213 private intrank(Key key, Node x) {214 if (x == null)215 return 0;216 int cmp =key.compareTo(x.key);217 if (cmp < 0)218 returnrank(key, x.left);219 else if (cmp > 0)220 return 1 + size(x.left) +rank(key, x.right);221 else

222 returnsize(x.left);223 }224 /**

225 * 删除最小键值对226 */

227 public voiddeleteMin(){228 root =deleteMin(root);229 }230 /**

231 * 不断深入根节点的左子树直到遇见一个空链接,然后将指向该节点的链接指向该结点的右子树232 * 此时已经没有任何链接指向要被删除的结点,因此它会被垃圾收集器清理掉233 *@paramx234 *@return

235 */

236 privateNode deleteMin(Node x){237 if(x.left == null) returnx.right;238 x.left =deleteMin(x.left);239 x.n = 1 + size(x.left)+size(x.right);240 returnx;241 }242

243 public voiddeleteMax(){244 root =deleteMax(root);245 }246 privateNode deleteMax(Node x){247 if(x.right == null ) returnx.left;248 x.right =deleteMax(x.right);249 x.n = size(x.left)+size(x.right) + 1;250 returnx;251 }252

253 public voiddelete(Key key){254 root =delete(root,key);255 }256 privateNode delete(Node x, Key key){257 if(x == null) return null;258 int cmp =key.compareTo(x.key);259 if(cmp < 0) x.left =delete(x.left,key);260 else if(cmp > 0) x.right =delete(x.right,key);261 else{262 if(x.right == null) returnx.left;263 if(x.left == null ) returnx.right;264 /**

265 * 如果被删除节点有两个子树,将被删除节点暂记为t266 * 从t的右子树中选取最小的节点x,将这个节点x的左子树设为t的左子树267 * 这个节点x的右子树设为t的右子树中删除了最小节点的子树,这样就成功替换了t的位置268 */

269 Node t =x;270 x =min(t.right);271 x.right =deleteMin(t.right);272 x.left =t.left;273 }274 x.n = size(x.left) + size(x.right) +1;275 returnx;276 }277

278 publicString toString(){279 StringBuilder sb = newStringBuilder();280 toString(root,sb);281 sb.deleteCharAt(sb.length()-1);282 returnsb.toString();283 }284 private voidtoString(Node x, StringBuilder sb){285 if(x == null ) return;286 toString(x.left,sb);287 sb.append(",");288 toString(x.right,sb);289 }290

291 public Listkeys(){292 returnkeys(min(),max());293 }294 public Listkeys(Key lo, Key hi){295 List list = new ArrayList();296 keys(root, list, lo, hi);297 returnlist;298 }299 private void keys(Node x, Listlist, Key lo, Key hi){300 if(x == null) return;301 int cmplo =lo.compareTo(x.key);302 int cmphi =hi.compareTo(x.key);303 if(cmplo < 0) keys(x.left,list,lo,hi);304 if(cmplo <= 0 && cmphi >= 0) list.add(x.key);305 if(cmphi > 0) keys(x.right,list,lo,hi);306 }307 public static voidmain(String[] args){308 BST bst = new BST();309 bst.put(5, "e");310 bst.put(1, "a");311 bst.put(4, "d");312 bst.put(9, "i");313 bst.put(10, "j");314 bst.put(2, "b");315 bst.put(7, "g");316 bst.put(3, "c");317 bst.put(8, "h");318 bst.put(6, "f");319 List keys =bst.keys();320 for(intkey : keys){321 System.out.print(",");322 }323 System.out.println();324 bst.deleteMin();325 System.out.println(bst.toString());326 bst.deleteMax();327 System.out.println(bst.toString());328 bst.delete(7);329 System.out.println(bst.toString());330 }331 }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值