insert()方法。这是我一开始听完课之后想到的insert方法,是错的。因为current为null的时候,用newNode替代current,但是此时的current已经是null,和原来的节点不存在子节点的关系。
public void insert(int key){ Node newNode = new Node(key); if (root == null){ root = newNode; return; } Node current = root; while (true){ if (key < current.key){ current = current.left; if (current == null){ current = newNode; return; } } else { current = current.right; if (current == null){ current = newNode; return; } } } }需要新建立一个节点(parent代替),然后用parent.left指向新插入的节点,将整个tree连接起来。
public void insert(int key){ Node newNode = new Node(key); if (root == null){ root = newNode; return; } Node current = root; Node parent = null; while (true){ parent = current; if (key < current.key){ current = current.left; if (current == null){ parent.left = newNode; return; } } else { current = current.right; if (current == null){ parent.right = newNode; return; } } } }
find() 函数,如果未找到值,则返回-1。返回类型其实也可以改成boolean。
//Return -1 if not found public int find(int key){ if (root == null) return -1; Node current = root; while (true){ if (key < current.key){ current = current.left; } else if (key > current.key){ current = current.right; } else { return current.key; } } }
remove()方法是BST的难点,要分类讨论。
1. 要删除的node(current)没有child. 此时只要将该node的parent子节点设置为null。加入了boolean类型变量isLeftChild要判断要删除的node是left child or right child, if it is a left child, then set parent.left = null; otherwise set parent.right = null;
2. 要删除的node(current)只有left child或right child. 比如只有left child时,还是要用到isLeftChild变量,当current是左节点时,set parent.left = current.left. current是右节点时, set parent.right = current.left.
3. 要删除的node(current)既有left child 也有right child. 以right child 为新的root,寻找最小值min作为代替current的replacement(代码中getReplacement函数),找到replacement之后记得要将被取出的replacement下的节点与replacementParent连接起来。同样需要用到isleftchild变量。
public boolean remove(int key){ Node current = root; Node parent = null; boolean isLeftChild = true; while (current.key != key){ parent = current; if (key < current.key){ current = current.left; isLeftChild = true; } else if (key > current.key){ current = current.right; isLeftChild = false; } else { return false; } } //The node to be removed has no child if (current.left == null && current.right == null){ if (current == root){ root = null; } if (isLeftChild){ parent.left = null; } else { parent.right = null; } } //The node to de removed has left child else if (current.left != null && current.right ==null){ if (current == root){ root = root.left; } else if (isLeftChild){ parent.left = current.left; } else { parent.right = current.left; } } else if (current.left == null && current.right != null){ if (current == root){ root = root.right; } else if (isLeftChild){ parent.left = current.right; } else { parent.right = current.right; } } else { Node replacement = getReplacement(current); if (current == root){ root = replacement; } else if (isLeftChild){ parent.left = replacement; } else { parent.right = replacement; } replacement.left = current.left; } return true; } public Node getReplacement(Node removeNode){ Node replacement = null; Node replacementParent = null; Node current = removeNode.right; while(current != null){ replacementParent = replacement; replacement = current; current = current.left; } if (replacement != removeNode.right){ replacementParent.left = replacement.right; replacement.right = removeNode.right; } return replacement; }