- 基本概念:
关于二叉查找树的概念我就不在这里说了,可以查看之前的一篇博客二叉树初看。这里主要写对二叉查找树的java 实现吧。 - java实现
1) 二叉查找树数据结构:
private class TreeNode {
private int key;
private TreeNode leftChild;
private TreeNode rightChild;
private TreeNode parent;
public TreeNode(int key, TreeNode leftChild, TreeNode rightChild,
TreeNode parent) {
this.key = key;
this.leftChild = leftChild;
this.rightChild = rightChild;
this.parent = parent;
}
public int getKey() {
return key;
}
public String toString() {
String leftkey = (leftChild == null ? "" : String
.valueOf(leftChild.key));
String rightkey = (rightChild == null ? "" : String
.valueOf(rightChild.key));
return "(" + leftkey + " , " + key + " , " + rightkey + ")";
}
}
2)查找节点
/**
* 查找给定的关键字
* */
public TreeNode search(int key) {
TreeNode pNode = root;
while(pNode != null && pNode.key != key) {
if(pNode.key > key) {
pNode = pNode.leftChild;
} else {
pNode = pNode.rightChild;
}
}
return pNode;
}
/**
* 查找最小关键字节点
* @throws Exception
* */
public TreeNode minKeyTreeNode(TreeNode node) throws Exception {
if(node == null) {
throw new Exception("树为空");
}
TreeNode pNode = node;
while(pNode.leftChild != null) {
pNode = pNode.leftChild;
}
return pNode;
}
/**
* 查找最大关键字的节点
* @throws Exception
* */
public TreeNode maxKeyTreeNode(TreeNode node) throws Exception {
if(node == null) {
throw new Exception("树为空");
}
TreeNode pNode = node;
while(pNode.rightChild != null) {
pNode = pNode.rightChild;
}
return pNode;
}
/**
* 获取给定节点的在中序遍历的条件下的后继节点
* 有三个情况:1)如果当前节点有右孩子,则后继是右子树的最左节点
* 2)当前节点无右孩子,如果当前节点是父亲节点的左儿子,则后继是父亲节点
* 3)当前节点无右孩子,且是父亲节点的右孩子,则所在字树遍历完了,向上寻找一个作为左孩子的祖先节点,那下一个遍历的是该祖先节点的父亲节点。
* 如果上面的情况都没有,则该节点是树的最后一个节点,无后继节点。
* */
public TreeNode successorInOrder(TreeNode node) throws Exception {
if(node == null) {
return null;
}
// 如果该节点的右节点不为空,则其后继节点就是右子树中的最小关键字节点
if(node.rightChild != null) {
return minKeyTreeNode(node.rightChild);
}
TreeNode parentNode = node.parent;
while (parentNode != null && node == parentNode.rightChild) {
node = parentNode;
parentNode = parentNode.parent;
}
return parentNode;
}
/**
* 获取给定节点在中序条件下的前序节点
* 如果x有左孩子,则前驱节点是左子树中最大关键字节点
* x无左孩子,若x是父亲节点的右孩子,则x的前驱节点为其父亲节点
* x无左孩子,x是父亲节点的左孩子,则x的前驱节点是x的某一个祖先节点的父亲节点,并且该祖先节点是其父亲节点的右孩子
* */
public TreeNode presuccessor(TreeNode node) {
if(node == null) {
return null;
}
if(node.leftChild != null) {
return maxKeyTreeNode(node.leftChild);
}
TreeNode parentNode = node.parent;
while(parentNode != null && node == parentNode.leftChild) {
node = parentNode;
parentNode = parentNode.parent;
}
return parentNode;
}
3) 插入节点
/**
* 将给定的关键字插入到二叉查找树中
* */
public void insert(int key) {
TreeNode parentNode = null;
TreeNode newNode = new TreeNode(key, null, null, null);
TreeNode pNode = root;
if (root == null) {
root = newNode;
return ;
}
while(pNode != null) {
parentNode = pNode;
if(key < pNode.key) {
pNode = pNode.leftChild;
} else if(key > pNode.key) {
pNode = pNode.rightChild;
} else {
return ; // 二叉查找树中已经存在要插入的关键字,返回
}
}
if(key < parentNode.key) {
parentNode.leftChild = newNode;
newNode.parent = parentNode;
} else {
parentNode.rightChild = newNode;
newNode.parent = parentNode;
}
}
4) 删除节点
/**
* 删除节点
* @throws Exception
* */
public void delete(int key) throws Exception {
TreeNode pNode = search(key);
if(pNode == null) {
throw new Exception("树中不存在要删除的关键字");
}
delete(pNode);
}
/**
* 从二叉查找树中删除给定的节点
* 前置条件:给定节点在二叉查找树中已经存在
* @throws Exception
* */
public void delete(TreeNode pNode) throws Exception {
if(pNode == null) {
return ;
}
if(pNode.leftChild == null && pNode.rightChild == null) {
TreeNode parentNode = pNode.parent;
if(parentNode == parentNode.leftChild) {
parentNode.leftChild = null;
} else {
parentNode.rightChild = null;
}
return ;
}
if(pNode.leftChild == null && pNode.rightChild != null) {
TreeNode parentNode = pNode.parent;
if(pNode == parentNode.leftChild) {
parentNode.leftChild = parentNode.rightChild;
pNode.rightChild.parent = parentNode;
} else {
parentNode.rightChild = pNode.rightChild;
pNode.rightChild.parent = parentNode;
}
return ;
}
if(pNode.leftChild != null && pNode.rightChild == null) {
TreeNode parentNode = pNode.parent;
if(pNode == parentNode.leftChild) {
parentNode.leftChild = pNode.leftChild;
pNode.leftChild.parent = parentNode;
} else {
parentNode.rightChild = pNode.leftChild;
pNode.rightChild.parent = parentNode;
}
return ;
}
// 该结点左右孩子结点均非空,则删除该结点的后继结点,并用该后继结点取代该结点
TreeNode successorNode = successorInOrder(pNode);//找到该节点的后继节点
delete(successorNode);
pNode.key = successorNode.key;
}
5) 遍历二叉树