二叉查找树的实现
- 首先构架一颗二叉查找树:
- 对于该二叉树:
先序遍历:6,2,1,5,3,4,7,8
中序遍历:1,2,3,4,5,6,7,8
后序遍历:1,4,3,5,2,8,7,6
- 对于删除操作.
- 若删除的节点尾叶子节点,则直接删除
- 若删除的节点存在一个叶子节点,则将当前节点父节点的引用直接指向当前节点的子节点(叶子节点)
- 若删除的节点存在两个节点,需要将当前节点的右子树中最小的节点值赋给当前节点,再将当前节点删除;
新建一个Node对象;
package com.deng.tree;
public class Node {
int key;
int value;
Node leftChild;
Node rightChild;
public Node(int key, int value) {
this.key = key;
this.value = value;
}
public void displayNode() {
}
}
建立一个二叉查找树
package com.deng.tree;
public class Tree {
Node root;
/*
* 查找节点
*/
public Node find(int key) {
Node currentNode = root;// 若当前节点就是根节点
while (currentNode != null && currentNode.key != key) {// 根节点不为空时,小于左查,大于右查
if (key < currentNode.key) {
currentNode = currentNode.leftChild;
} else {
currentNode = currentNode.rightChild;
}
}
return currentNode;
}
/*
* 插入节点
*/
public void insert(int key, int value) {
if (root == null) {// 若根节点尾空,初始化根节点,插入此位置
root = new Node(key, value);
return;
}
// 定义两个节点,一个表示父节点,一个表示当前节点
Node currentNode = root;
Node parentNode = root;
boolean isLeftChild = true;
while (currentNode != null) {
parentNode = currentNode;
if (key < currentNode.key) {
currentNode = currentNode.leftChild;
isLeftChild = true;
} else {
currentNode = currentNode.rightChild;
isLeftChild = false;
}
}
Node newNode = new Node(key, value);
if (isLeftChild) {
parentNode.leftChild = newNode;
} else {
parentNode.rightChild = newNode;
}
}
/*
* 删除节点: 1.若当前节点尾叶子节点直接删除; 2.若当前节点有一个孩子节点,只需将该节点的父节点的左孩子节点引用指向当前节点的孩子节点即可
* 3.若当前节点有两个孩子节点, (1),首先对当前节点的父节点,进行中循遍历,获得当前节点的后继节点的值,并删除当前节点 (2)而后将该值赋给当前节点即可
*/
public boolean delete(int key) {
Node currentNode = root;
Node parentNode = root;
boolean isleftChild = true;
while (currentNode != null && currentNode.key != key) {
parentNode = currentNode;
if (key < currentNode.key) {
currentNode = currentNode.leftChild;
isleftChild = true;
} else {
currentNode = currentNode.rightChild;
isleftChild = false;
}
}
if (currentNode == null) {
return false;
}
if (currentNode.leftChild == null && currentNode.rightChild == null) {
// 要删除的节点是叶子节点,直接删除
if (currentNode == root) {
root = null;
} else if (isleftChild) {
parentNode.leftChild = null;
} else {
parentNode.rightChild = null;
}
} else if (currentNode.rightChild == null) {// 要删除的只有左孩子节点
if (currentNode == root) {
root = currentNode.leftChild;
} else if (isleftChild) {
parentNode.leftChild = currentNode.leftChild;
} else {
parentNode.rightChild = currentNode.leftChild;
}
} else if (currentNode.leftChild == null) {// 要删除的节点只有有孩子
if (currentNode == root) {
root = currentNode.rightChild;
} else if (isleftChild) {
parentNode.leftChild = currentNode.rightChild;
} else {
parentNode.rightChild = currentNode.rightChild;
}
} else {// 要删除的节点既有左孩子又有有孩子节点
// 用待删除节点右子树中的key值最小节点的值来替代要删除的节点的值,然后删除右子树中key值最小的节点
Node directPostNode = getDirectPostNode(currentNode);
currentNode.key = directPostNode.key;
currentNode.value = directPostNode.value;
}
return true;
}
/*
* 该方法为得到待删节点的直接后继节点
*/
private Node getDirectPostNode(Node delNode) {
Node parentNode = delNode;// 用来保存待删节点的直接后继节点的父亲节点
Node directPostNode = delNode;// 用来保存待删节点的直接后继节点
Node currentNode = delNode.rightChild;
while (currentNode != null) {
parentNode = directPostNode;
directPostNode = currentNode;
currentNode = currentNode.leftChild;
}
if (directPostNode != delNode.rightChild) {// 从树中删除此直接后继节点
parentNode.leftChild = directPostNode.rightChild;
directPostNode.rightChild = null;
}
return directPostNode;// 返回次直接后继节点
}
/*
* 先序遍历
*/
public void preOrder(Node rootNode) {
if (rootNode != null) {
System.out.println(rootNode.key + " " + rootNode.value);
preOrder(rootNode.leftChild);
preOrder(rootNode.rightChild);
}
}
/*
* 中序遍历
*/
public void inOrder(Node rootNode) {
if (rootNode != null) {
inOrder(rootNode.leftChild);
System.out.println("key:" + rootNode.key + " " + "value:" + rootNode.value);
inOrder(rootNode.rightChild);
}
}
/*
* 后序遍历
*/
public void postOrder(Node rootNode) {
if (rootNode != null) {
postOrder(rootNode.leftChild);
postOrder(rootNode.rightChild);
System.out.println(rootNode.key + " " + rootNode.value);
}
}
}
测试结果:
package com.deng.tree;
public class BST_tes {
public static void main(String[] args) {
Tree tree = new Tree();
// 插入操作构建一颗二叉树
tree.insert(1, 1);
tree.insert(2, 2);
tree.insert(3, 3);
tree.insert(4, 4);
tree.insert(5, 5);
tree.insert(6, 6);
tree.insert(7, 7);
tree.insert(8, 8);
System.out.println("删除前中序遍历结果:");
tree.inOrder(tree.root);// 中序遍历
tree.delete(5);
System.out.println("---------删除节点5之后的中序遍历:----------");
tree.inOrder(tree.root);
}
}