java学习笔记 二叉树
//BsTreeNode的定义
public class BsTreeNode<T extends Comparable> {
//关键字(键值)
T nodeKey;
//左节点引用
BsTreeNode left;
//右节点引用
BsTreeNode right;
//父节点引用,删除操作会用到
BsTreeNode parent;
//构造方法 结点的值
public BsTreeNode() {
}
public BsTreeNode(T value) {
this.nodeKey = value;
}
public T getNodeKey() {
return nodeKey;
}
@Override
public String toString() {
return nodeKey.toString();
}
public BsTreeNode<T> getLeft() {
return left;
}
public void setLeft(BsTreeNode<T> left) {
this.left = left;
}
public BsTreeNode<T> getRight() {
return right;
}
public void setRight(BsTreeNode<T> right) {
this.right = right;
}
/*
* 中序遍历BsTree,打印节点值(递归实现)
* */
public void inOrder(BsTreeNode<T> root){
if(root == null){
return;
}
inOrder(root.left);
System.out.println("->"+root.toString());
inOrder(root.right);
}
/*
使用递归实现BsTree查找
@param root BST根节点引用
@param key 待查找的节点值
@return 命中的节点
*/
public BsTreeNode<T> searchRecursively(BsTreeNode<T> root, T key){
if(root == null){
return null; //空指针处理
}
if(root.getNodeKey().compareTo(key)>0){
//当前节点值比搜索值大,左子树查找
return searchRecursively(root.getLeft(),key);
}else if(root.getNodeKey().compareTo(key)<0){ //这几个if把原文的NodeKey替换了。原本是Value
//当前节点值比搜索值小,右子树查找
return searchRecursively(root.getRight(),key);
}else {return root;} //查找命中
}
/*
使用递归实现BsTree插入
@param root BST根节点引用
@param key 待插入的节点值
@return 插入成功返回true,如果树中有该元素不需要插入则返回false
*/
public boolean insertRecursively(BsTreeNode<T> root, T key){
if(root.nodeKey.compareTo(key)>0){
if(root.left == null){
BsTreeNode<T> node = new BsTreeNode<>(key);//将key赋值给新节点
root.left = node;
node.parent = root;
return true;
}else{
return insertRecursively(root.left,key);
}
}else if (root.nodeKey.compareTo(key)<0){
if(root.right == null){
BsTreeNode<T> node = new BsTreeNode<>(key);//将key赋值给新节点
root.right = node;
node.parent = root;
return true;
}else{
return insertRecursively(root.right,key);
}
}else {
return false; //该节点被遍历到了,已存在,无法插入
}
}
//插入位置一定是叶子位置,不会导致树结构调整,插入操作极为简单
/**
* 利用二分查找实现BsTree插入过程
*/
public boolean insertRecursively(BsTreeNode<T> root, BsTreeNode<T> nodeInserted){
if(root == null){
root = nodeInserted;
return true;
} if(root.nodeKey.compareTo(nodeInserted.nodeKey)>0){ //在左子树找插入位置(叶子节点位置),构造一个新的节点
// 作为叶子节点插入 BST
if(root.left == null){
root.left = nodeInserted;
nodeInserted.parent = root; //设置新节点parent
return true;
}else{
return insertRecursively(root.left, nodeInserted);
}
}else if(root.nodeKey.compareTo(nodeInserted.nodeKey)<0){ //在右子树找插入位置(叶子节点位置),构造一个新的节点
// 作为叶子节点插入 BST
if(root.right == null){
root.right = nodeInserted;
nodeInserted.parent = root; //设置新节点parent
return true;
}else{
return insertRecursively(root.right, nodeInserted);
}
}else {
return false;
}
}
/*删除操作,四种情形
1. 叶子节点
2. 只有左子树节点
3. 只有右子树的节点
4. 左右子树都有的节点
* */
public void deleteRecursively(BsTreeNode currentNode, T key){
if(currentNode ==null){
System.out.println(“不存在该节点”);
return;
}
//查找
//当前节点键值大于key,去左子树查找
if(currentNode.nodeKey.compareTo(key)>0){
deleteRecursively(currentNode.left,key); //递归
}
//当前节点键值小于key,去右子树查找
if(currentNode.nodeKey.compareTo(key)<0){
deleteRecursively(currentNode.right,key); //递归
}
//当前节点键值 = key,开始进行删除操作
else {
//1.对于第一种情形,左右子树均为空,直接删掉,不影响树结构调整
if (currentNode.right == null && currentNode.left == null) {
//通过父节点删除节点
BsTreeNode parent = currentNode.parent; //这里的第一个parent 局部变量,不影响
if (parent.left == currentNode) {
parent.left = null;
}
if (parent.right == currentNode) {
parent.right = null;
}
return;
}
else if (currentNode.right ==null){
//2.第二种情形,将左子树替换被删除节点
BsTreeNode rootLeft = currentNode.left;
T temp = rootLeft.nodeKey;
currentNode.left = rootLeft.left; //令被删除节点的左节点变为下一个节点的左节点,上移
currentNode.right = rootLeft.right;
currentNode.nodeKey = temp;//改变键值
//修正parent 现在rootleft.left/right 的父节点还不是currentNode,是rootleft = currentNode.left
if(currentNode.left!=null){
rootLeft.left.parent = currentNode;
}
if(currentNode.right!=null){
rootLeft.right.parent = currentNode;
}
}else if(currentNode.left ==null){
//3.第3种情形,将右子树替换被删除节点
BsTreeNode rootRight = currentNode.right; //一个右节点
T temp = rootRight.nodeKey;//右节点的键值
currentNode.left = rootRight.left;//挪动树
currentNode.right = rootRight.right;
currentNode.nodeKey = temp; //改变键值
//修正parent,将rootRight的左右子节点指向传递进来的参数currentNode
if(currentNode.left!=null){
rootRight.left.parent = currentNode;
}
if(currentNode.right!=null){
rootRight.right.parent = currentNode;
}
}else{
// 第四种 找到当前节点的中序前驱节点(或直接后继)代替待删除节点,同时在
// 二叉排序树中对其做删除操作
//当前节点的中序前驱节点
BsTreeNode<T> node = currentNode.left;
while(node.right!=null){
node = node.right; //找直接前驱
}
//节点内容替换
currentNode.nodeKey = node.nodeKey;
//删除前驱节点
deleteRecursively(node,node.nodeKey);
}
}
}
}