学习数据结构和算法的日常Demo
查找二叉树中指定节点
查找要求
- 编写前序查找,中序查找和后序查找的方法
- 根据传入的value值,分别使用三种查找方式查找value对应的树节点
代码实现
public class TreeNode {
private int value;
private TreeNode left;
private TreeNode right;
public TreeNode(int value) {
this.value = value;
}
@Override
public String toString() {
return "TreeNode{" +
"value=" + value +
'}';
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public TreeNode getLeft() {
return left;
}
public void setLeft(TreeNode left) {
this.left = left;
}
public TreeNode getRight() {
return right;
}
public void setRight(TreeNode right) {
this.right = right;
}
// 前序遍历查找指定节点
public TreeNode preSearch(int value) {
// 先和根节点比较
if (this.value == value) {
return this;
}
// 从左子树开始递归查找
TreeNode tree = null;
if (this.left != null) {
tree = this.left.preSearch(value);
}
if (tree != null) {
// 说明左子树递归中找到了
return tree;
}
// 从右子树开始递归查找
if (this.right != null) {
tree = this.right.preSearch(value);
}
return tree;
}
// 中序遍历查找指定节点
public TreeNode infixSearch(int value) {
// 从左子树开始递归查找
TreeNode tree = null;
if (this.left != null) {
tree = this.left.infixSearch(value);
}
if (tree != null) {
// 说明左子树递归中找到了
return tree;
}
// 和根节点比较
if (this.value == value) {
return this;
}
// 从右子树开始递归查找
if (this.right != null) {
tree = this.right.infixSearch(value);
}
return tree;
}
// 后序遍历查找指定节点
public TreeNode postSearch(int value) {
// 从左子树开始递归查找
TreeNode tree = null;
if (this.left != null) {
tree = this.left.postSearch(value);
}
if (tree != null) {
// 说明左子树递归中找到了
return tree;
}
// 从右子树开始递归查找
if (this.right != null) {
tree = this.right.postSearch(value);
}
if (tree != null) {
// 说明右子树递归中找到了
return tree;
}
// 和根节点比较
if (this.value == value) {
return this;
}
return tree;
}
}
public class BinaryTree {
private TreeNode root;
public TreeNode getRoot() {
return root;
}
public void setRoot(TreeNode root) {
this.root = root;
}
// 前中后查找
public TreeNode preSearch(int value) {
if (root != null) {
return root.preSearch(value);
}
return null;
}
public TreeNode infixSearch(int value) {
if (root != null) {
return root.infixSearch(value);
}
return null;
}
public TreeNode postSearch(int value) {
if (root != null) {
return root.postSearch(value);
}
return null;
}
}
public class BinaryTreeDemo {
public static void main(String args[]) {
BinaryTree tree = new BinaryTree();
TreeNode root = new TreeNode(33);
TreeNode node1 = new TreeNode(18);
TreeNode node2 = new TreeNode(63);
TreeNode node3 = new TreeNode(77);
TreeNode node4 = new TreeNode(51);
TreeNode node5 = new TreeNode(9);
TreeNode node6 = new TreeNode(24);
TreeNode node7 = new TreeNode(100);
// 构建树
root.setLeft(node1);
root.setRight(node2);
node1.setLeft(node5);
node1.setRight(node6);
node2.setLeft(node4);
node2.setRight(node3);
node3.setRight(node7);
// 创建根节点
tree.setRoot(root);
/*
33
18 63
9 24 51 77
100
*/
System.out.println("前序查找:"+tree.preSearch(18));
System.out.println("前序查找:"+tree.preSearch(180));
System.out.println("中序查找:"+tree.infixSearch(63));
System.out.println("后序查找:"+tree.postSearch(51));
}
}
删除二叉树指定节点
删除要求
- 根据传入的value值,删除value对应的树节点
- 如果删除的节点是根节点,则整树置为空
- 如果删除的节点是叶子节点,则删除该节点
- 如果删除的节点是非叶子节点,则删除该子树
删除思路
代码实现
// TreeNode.class
public void delete(int value) {
// 如果当前节点的左子节点不为空,并且就是要删除的
if (this.left != null && this.left.value == value) {
this.left = null;
return;
}
// 如果当前节点的右子节点不为空,并且就是要删除的
if (this.right != null && this.right.value == value) {
this.right = null;
return;
}
// 向左子树继续递归
if (this.left != null) {
this.left.delete(value);
}
// 向右子树继续递归
if (this.right != null) {
this.right.delete(value);
}
}
// BinaryTree.class
public void delete(int value) {
if (root != null) {
// 判断root是否为要删除节点
if (root.getValue() == value) {
root = null; // 置空
} else {
root.delete(value);
System.out.println("删除成功!");
}
} else {
System.out.println("树为空!");
}
}
// BinaryTreeDemo.class
/*
33
18 63
9 24 51 77
100
*/
System.out.println("删除前:");
tree.preOrder();
System.out.println();
tree.delete(18);
System.out.println("删除后:");
tree.preOrder();
删除前(前序遍历):
TreeNode{value=33} TreeNode{value=18} TreeNode{value=9} TreeNode{value=24} TreeNode{value=63} TreeNode{value=51} TreeNode{value=77} TreeNode{value=100}
删除成功!
删除后(前序遍历):
TreeNode{value=33} TreeNode{value=63} TreeNode{value=51} TreeNode{value=77} TreeNode{value=100}
删除改进(存在bug)
- 根据传入的value值,删除value对应的树节点
- 如果删除的节点是根节点,则整树置为空
- 如果删除的节点是叶子节点,则删除该节点
- 如果删除的节点是非叶子节点,则进行如下判断:
代码实现
// TreeNode.class
// 递归删除节点
// 如果是叶子节点,则删除该节点
// 若非叶子节点,1.子节点只有一个,则该子节点替换之;
// 2.有左右子节点,则左节点替换之(即右子节点成为该左节点的子节点)
// 若是根节点,将树置空
public void delete2(int value) {
// 如果当前节点的左子节点不为空,并且就是要删除的
if (this.left != null && this.left.value == value) {
// 判断该左子节点(它)下面是否还包含左右子节点
// 1.如果它的左右子节点均不为空,则让它的左子节点取代之,并且它的右子节点成为左子节点的新右子节点(bug-->如果它的左子节点本身有右子节点,导致强行覆盖)
if (this.left.left != null && this.left.right != null) {
this.left.left.right = this.left.right; // 会出现覆盖问题
this.left = this.left.left;
} else if (this.left.left == null || this.left.right == null){
// 2.若它下面只有一个子节点,就进行该判断:有左加左,无左加右
this.left = (this.left.left == null ? this.left.right : this.left.left);
}else {
// 3.当前节点的子节点下再无任何子树
this.left = null;
}
return;
}
// 如果当前节点的右子节点不为空,并且就是要删除的
if (this.right != null && this.right.value == value) {
// 判断该左子节点(它)下面是否还包含左右子节点
// 如果它的左右子节点均不为空,则让它的左子节点取代之,并且它的右子节点成为左子节点的右子节点
if (this.right.left != null && this.right.right != null) {
this.right.left.right = this.right.right; // 出现覆盖问题
this.right = this.right.left;
} else if (this.right.left == null || this.right.right == null){
// 若它下面只有一个子节点,就进行该判断:有左加加左,无左加右
this.right = (this.right.left == null ? this.right.right : this.right.left);
}else {
this.right = null;
}
return;
}
// 向左子树继续递归
if (this.left != null) {
this.left.delete2(value);
}
// 向右子树继续递归
if (this.right != null) {
this.right.delete2(value);
}
}
// BinaryTree.class
// 改进了对子树的删除
public void delete2(int value) {
if (root != null) {
// 判断root是否为要删除节点
if (root.getValue() == value) {
root = null; // 置空
} else {
root.delete2(value);
System.out.println("删除成功!");
}
} else {
System.out.println("树为空!");
}
}
// BinaryTreeDemo.class
/*
33
18 63
9 24 51 77
100
*/
System.out.println("删除前:");
tree.preOrder();
System.out.println();
tree.delete2(18);
System.out.println("删除后:");
tree.preOrder();
System.out.println(node5 + "的右节点为:" + node5.getRight());
删除前(前序遍历):
TreeNode{value=33} TreeNode{value=18} TreeNode{value=9} TreeNode{value=24} TreeNode{value=63} TreeNode{value=51} TreeNode{value=77} TreeNode{value=100}
删除成功!
删除后(前序遍历):
TreeNode{value=33} TreeNode{value=9} TreeNode{value=24} TreeNode{value=63} TreeNode{value=51} TreeNode{value=77} TreeNode{value=100}
< TreeNode{value=9}的右节点为:TreeNode{value=24} >