文章目录
1.二叉树概念
概念:二叉树是一棵树,其中每个节点不能多于两个儿子
2.图解分析
2.1 模拟器地址
二叉树:https://www.cs.usfca.edu/~galles/visualization/BST.html
所有数据结构:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
2.2添加
如果依次添加6,2,1,4,3,5,8节点,结果如下图
第一个添加的节点为根,后面添加的节点大于根往右,小于根往左
2.3 删除
2.3.1 删除节点1
- 第一步:1小于6 向左寻找到2
- 第二步:1小于2 向左寻找1
- 第三步:设置2的左边节点为节点1的左边节点(如果有左边节点的话) 图中为null
- 第三步核心代码:
root = (root.left != null) ? root.left : root.right;
2.3.2 删除节点2
- 第一步:2小于6 向左寻找到3
- 第二步:2小于3 向左寻找到2
- 第三步:设置3的左边节点为2的左边节点
- 第三步核心代码:
root = (root.left != null) ? root.left : root.right;
- ps:第一种情况何和第二种情况本质上是一样的,只是第一种情况恰好被删除节点没有儿子
2.3.3 删除节点4
当需要删除的节点有左右两个儿子的时候
2.3.3.1第一种实现方式
- 第一步:4小于6 向左寻找到2
- 第二步:4大于2 向右寻找4为删除节点
- 第三步:找到4节点右树中最小的节点5作为替换节点
- 第四步:设置2的右节点为5(只替换节点本身,原左边3自动转化为节点5的左边节点)
- 第五步:删除原来5节点中的5节点 剩余节点为5的右节点
- 核心代码:
//找到右树中的最小节点5代替4
root.element = findMin(root.right).element; //找到5
//删除原来5节点中的5节点 剩余节点为5的右节点
root.right = remove(root.element, root.right);
//root.left 还是原来的3
2.3.3.2第二种实现方式
- 第一步:4小于6 向左寻找到2
- 第二步:4大于2 向右寻找4为删除节点
- 第三步:找到4节点左树中最大的节点3作为替换节点
- 第四步:设置2的右节点为3(只替换节点本身,原右边5自动转化为节点3的右边节点)
- 第五步:删除原来3节点中的3节点 剩余节点为3的左节点
- 核心代码:
//找到左树中的最大节点3代替4
root.element = findMax(root.left).element; //找到3
//删除原来3节点中的3节点 剩余节点为3的左节点
root.left= remove(root.element, root.left);
//root.right 还是原来的5
3.代码
3.1树节点
/**
* 二叉树节点
*/
public class BinaryNode<T> {
T element;
BinaryNode<T> left;
BinaryNode<T> right;
public BinaryNode(T element) {
this(element, null, null);
}
public BinaryNode(T element, BinaryNode<T> left, BinaryNode<T> right) {
this.element = element;
this.left = left;
this.right = right;
}
}
3.2插入
public void insert(T x) {
root = insert(x, root);
}
/**
* 添加节点
*
* @param x 插入节点
* @param root 根节点
*/
private BinaryNode<T> insert(T x, BinaryNode<T> root) {
//如果根节点为空,则当前x节点为根节点
if (null == root) {
return new BinaryNode(x);
}
int compareResult = x.compareTo(root.element);
//小于当前根节点 将x插入根节点的左边
if (compareResult < 0) {
root.left = insert(x, root.left);
} else if (compareResult > 0) {
//大于当前根节点 将x插入根节点的右边
root.right = insert(x, root.right);
} else {
}
return root;
}
3.3删除
/**
* 删除节点
*
* @param x 节点
* @param root 根节点
*/
private BinaryNode<T> remove(T x, BinaryNode<T> root) {
if (null == root) {
return root;
}
int compareResult = x.compareTo(root.element);
//小于当前根节点
if (compareResult < 0) {
root.left = remove(x, root.left);
} else if (compareResult > 0) {
//大于当前根节点
root.right = remove(x, root.right);
} else if (root.left != null && root.right != null) {
//找到右边最小的节点
root.element = findMin(root.right).element;
//当前节点的右边等于原节点右边删除已经被选为的替代节点
root.right = remove(root.element, root.right);
} else {
root = (root.left != null) ? root.left : root.right;
}
return root;
}
3.4 完整代码
public class BinarySearchTree<T extends Comparable<? super T>> {
private BinaryNode<T> root;
public void insert(T x) {
root = insert(x, root);
}
public void remove(T x) {
root = remove(x, root);
}
public T findMin() {
return findMin(root).element;
}
public void makeEmpty() {
root = null;
}
public boolean isEmpty() {
return root == null;
}
/**
* 添加节点
*
* @param x 插入节点
* @param root 根节点
*/
private BinaryNode<T> insert(T x, BinaryNode<T> root) {
//如果根节点为空,则当前x节点为根及诶单
if (null == root) {
return new BinaryNode(x);
}
int compareResult = x.compareTo(root.element);
//小于当前根节点 将x插入根节点的左边
if (compareResult < 0) {
root.left = insert(x, root.left);
} else if (compareResult > 0) {
//大于当前根节点 将x插入根节点的右边
root.right = insert(x, root.right);
} else {
}
return root;
}
/**
* 删除节点
*
* @param x 节点
* @param root 根节点
*/
private BinaryNode<T> remove(T x, BinaryNode<T> root) {
if (null == root) {
return root;
}
int compareResult = x.compareTo(root.element);
//小于当前根节点
if (compareResult < 0) {
root.left = remove(x, root.left);
} else if (compareResult > 0) {
//大于当前根节点
root.right = remove(x, root.right);
} else if (root.left != null && root.right != null) {
//找到右边最小的节点
root.element = findMin(root.right).element;
//当前节点的右边等于原节点右边删除已经被选为的替代节点
root.right = remove(root.element, root.right);
} else {
root = (root.left != null) ? root.left : root.right;
}
return root;
}
/**
* 找最小节点
*
* @param root 根节点
*/
private BinaryNode<T> findMin(BinaryNode<T> root) {
if (root == null) {
return null;
} else if (root.left == null) {
return root;
}
return findMin(root.left);
}
/**
* 找最大节点
*
* @param root 根节点
*/
private BinaryNode<T> findMax(BinaryNode<T> root) {
if (root == null) {
return null;
} else if (root.right == null) {
return root;
} else {
return findMax(root.right);
}
}
public void printTree() {
if (isEmpty()) {
System.out.println("节点为空");
} else {
printTree(root);
}
}
public void printTree(BinaryNode<T> root) {
if (root != null) {
System.out.print(root.element);
if (null != root.left) {
System.out.print("左边节点" + root.left.element);
}
if (null != root.right) {
System.out.print("右边节点" + root.right.element);
}
System.out.println();
printTree(root.left);
printTree(root.right);
}
}
}
4.测试
代码:
@Test
public void test2(){
BinarySearchTree testTree = new BinarySearchTree();
testTree.insert(6);
testTree.insert(2);
testTree.insert(8);
testTree.insert(1);
testTree.insert(4);
testTree.insert(3);
testTree.insert(5);
testTree.printTree();
testTree.remove(2);
System.out.println("======删除2节点之后======");
testTree.printTree();
}
测试截图:
5.参考书籍
《数据结构与算法分析》第三版
6.系列链接
下一篇:java实现AVL树