前言
对二叉树有一定了解之后,学习一下对二叉树的操作,有时候这些东西一学就忘,反复操作几回就熟了。
二叉树的概念已经了解了,那么得知道怎么操作。现在就讲讲怎么操作二叉树。
构建二叉树
首先得先种一颗树,然后才能操作树。
怎么构建?有哪些对象、需要什么方法?
主要对象
- Node 节点对象
- BinaryTree 树对象
Node 节点对象
作用:存数据的。
大白话就是树中的每一个节点,存着外面进来的数据。最简单的理解就是HashMap
就是一颗树的实现,每次不明白,就想想HashMap
,是不是就通了。
四个关键要素:
- left
- right
- key
- value
BinaryTree 对象
作用:操作node节点数据,维护树结构。
大白话,就是把Node拼起来,成为一颗大树。
主要操作:
- put
- get
- delete
- size
- min
- max
put 完以后要返回整棵树,开始是始于 root,返回也是返回 root。
实现
实现就是把Node
和BinaryTree
这两结合起来用,还用的没问题。
需要考虑几个问题:
- 怎么结合起来用
- 从哪开始写
怎么结合起来用?
即然要操作,那就需要对外暴露操作接口BinaryTree
就是最外操作的对象。
从哪开始写?
先定义数据结构,再定义方法。
查询 和 添加 逻辑基本相同,都是通过递归的形式。
删除比较麻烦,如果被删除的节点有子节点,不能让丢掉这些子节点,需要重新维护这些子节点。
删除的节点,左子树的所有节点一定比右子树的节点小,所以只需要从右子树中拿到最小的那个节点即可,也就是右子树中最左边的叶子节点。
删除步骤
找到要删除的 key
判断如果左子树为空,就用右边最小
判断如果右子树为空,就用左边最小
删除找到的最小值
将最小值替换被删除的节点,重新跟左右子节点建立连接
简化的情况
被删除节点只有一个 左子树 或 右子树,直接拿过来替换当前节点就行
实现代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
| import java.util.Queue; import java.util.concurrent.ArrayBlockingQueue;
public class BinaryTree<Key extends Comparable<Key>, Value> {
private Node root; private int size;
private class Node { public Node left; public Node right; public Key key; public Value value;
public Node(Key key, Value value, Node left, Node right) { this.left = left; this.right = right; this.key = key; this.value = value; } }
public void put(Key key, Value value) { root = put(root, key, value); }
private Node put(Node x, Key key, Value value) { if (x == null) { size++; return new Node(key, value, null, null); } int comp = key.compareTo(x.key); if (comp > 0) { x.right = put(x.right, key, value); } else if (comp < 0) { x.left = put(x.left, key, value); } else { x.value = value; } return x; }
public Value get(Key key) { return get(root, key); }
private Value get(Node x, Key key) { if (x == null) { return null; }
int comp = key.compareTo(x.key); if (comp > 0) { return get(x.right, key); } else if (comp < 0) { return get(x.left, key); } else { return x.value; } }
public int size() { return size; }
public Node delete(Key key) { return delete(root, key); }
private Node delete(Node x, Key key) { if (x == null) { return null; } int comp = key.compareTo(x.key); if (comp > 0) { x.right = delete(x.right, key); } else if (comp < 0) { x. left = delete(x.left, key); } else {
if (x.left == null) { size--; return x.right; } if (x.right == null) { size--; return x.left; } size--; Node minNode = x.right; while (minNode.left != null) { minNode = minNode.left; }
Node parent = x.right; while (parent.left != null) { if (parent.left.left != null) { parent.left = null; } else { parent = parent.left; } }
minNode.left = x.left; minNode.right = x.right;
return x; } return x; } }
|
总结
二叉树的构建和查找,相对比较简单,需要理清的是这个操作,有些写法经常不用就会忘。
为什么业务中用的东西不会忘,因为你天天在写,如果你天天写这些东西,你也不会忘的,唯手熟尔。