数据结构-二叉搜索树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 }
图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 }
图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 }
4,特别鸣谢
探究未知是最大乐趣