其他分享
首页 > 其他分享> > 【tree】二叉查找树

【tree】二叉查找树

作者:互联网

目录

 

系列目录

 


一、基本概念

1.二叉查找树的定义

二叉查找树:首先是一颗二叉树,其次对于树中的任意一个节点都有该节点的值大于左孩子小于右孩子。

二叉树的定义见第一篇博客《树》

需要实现的基本操作:查找结点、插入节点和删除节点。

2.查找节点

从根结点出发:

3.插入节点

从根结点出发:

4.删除节点

从根结点出发:

如下图所示:

 


二、递归实现

1.实现代码

package cn.wxy.blog;

import java.util.Objects;
import cn.wxy.blog.TraversalTreeTool.TreeNode;

/**
 * 递归实现二叉查找树
 * @author 王大锤
 * @date 2021年6月11日
 */
public class BinarySearchTree<K extends Comparable<K>, V> {
	static class Node<K extends Comparable<K>, V> implements TreeNode<K, Node<K, V>> {
		private K key;
		private V value;
		private Node<K, V> parent;
		private Node<K, V> leftChild;
		private Node<K, V> rightChild;

		public Node(K key, V value, Node<K, V> parent) {
			this.key = key;
			this.value = value;
			this.parent = parent;
		}

		public K getKey() {
			return key;
		}

		public void setKey(K key) {
			this.key = key;
		}

		public Node<K, V> getParent() {
			return parent;
		}

		public void setParent(Node<K, V> parent) {
			this.parent = parent;
		}

		public Node<K, V> getLeftChild() {
			return leftChild;
		}

		public void setLeftChild(Node<K, V> leftChild) {
			this.leftChild = leftChild;
		}

		public Node<K, V> getRightChild() {
			return rightChild;
		}

		public void setRightChild(Node<K, V> rightChild) {
			this.rightChild = rightChild;
		}

		@Override
		public String toString() {
			return this.key + ":" + value + " ";
		}
	}

	private Node<K, V> root;

	public BinarySearchTree() {
	}

	public Node<K, V> getRoot() {
		return this.root;
	}

	public void insert(K key, V value) {
		if (Objects.nonNull(key)) {
			// 通过this.root = insert来维护二叉树的根节点
			this.root = insert(key, value, this.root, null);
		}
	}

	/**
	 * 递归实现二叉查找树的节点插入:
	 * 1.如果插入key小于当前查找的节点,则往左走
	 * 2.如果插入key大于当前查找的节点,则往右走
	 * 3.如果插入key等于当前查找的节点,修改当前节点的value
	 * @param key 插入的key
	 * @param value 插入的value
	 * @param node 当前节点
	 * @param parent 当前节点的父节点
	 * @return
	 */
	private Node<K, V> insert(K key, V value, Node<K, V> node, Node<K, V> parent) {
		if (Objects.isNull(node))
			return new Node<K, V>(key, value, parent);
		int compare = key.compareTo(node.key);
		if (compare < 0)
			// 通过node.leftChild = insert在递归中来维护树的逻辑结构
			node.leftChild = insert(key, value, node.leftChild, node);
		else if (compare > 0)
			// 通过node.rightChild = insert在递归中来维护树的逻辑结构
			node.rightChild = insert(key, value, node.rightChild, node);
		else
			node.value = value;
		return node;
	}

	public V select(K key) {
		if (Objects.nonNull(key)) {
			Node<K, V> node = select(key, this.root);
			return Objects.nonNull(node) ? node.value : null;
		}
		return null;
	}

	/**
	 * 递归实现二叉查找树的节点查找:
	 * 1.如果查找key小于当前查找的节点,则往左走
	 * 2.如果查找key大于当前查找的节点,则往右走
	 * 3.如果查找key等于当前查找的节点,则返回该节点
	 * @param key 查找的key
	 * @param node 当前节点
	 * @return
	 */
	private Node<K, V> select(K key, Node<K, V> node) {
		if (Objects.isNull(node))
			return null;
		int compare = key.compareTo(node.key);
		if (compare < 0)
			return select(key, node.leftChild);
		else if (compare > 0)
			return select(key, node.rightChild);
		else
			return node;
	}

	public void remove(K key) {
		if (Objects.nonNull(key))
			// 通过this.root = remove来维护二叉查找树的根节点
			this.root = remove(key, this.root);
	}

	/**
	 * 递归实现二叉查找树的节点删除:
	 * 1.如果删除key小于当前查找的节点,则往左走
	 * 2.如果删除key大于当前查找的节点,则往右走
	 * 3.如果删除key等于当前查找的节点,则删除该节点
	 * 此时,删除节点分为两种情况:
	 * a.删除节点有两个孩子:这种情形,为了保证二叉排序树的顺序性(大于左孩子小于右孩子),需要从左子树或右子树中找一个最接近删除节点节点
	 * 即左子树的最大节点或右子树的最小节点
	 * 左子树的最大节点即左子树的最右节点
	 * 右子树的最小节点即右子树的最左节点
	 * 本例中选择右子树的最大节点(即右子树的最左节点)来代替删除节点位置,从而保证二叉查找树的有序性
	 * b.删除节点最多只有一个孩子:直接让子节点代替删除节点的位置
	 * @param key
	 * @param node
	 * @return
	 */
	private Node<K, V> remove(K key, Node<K, V> node) {
		if (Objects.isNull(node))
			return null;
		int compare = key.compareTo(node.key);
		if (compare < 0)
			// 通过node.leftChild = remove在递归中来维护树的逻辑结构
			node.leftChild = remove(key, node.leftChild);
		else if (compare > 0)
			// 通过node.rightChild = remove在递归中来维护树的逻辑结构
			node.rightChild = remove(key, node.rightChild);
		else {
			// 找到待删除结点,此时有两种情况:
			// a.待删除结点有两个孩子:本例中用待删除节点右子树的最小节点(即右子树的最左节点)来替换其位置
			// b.待删除结点最多有一个孩子:直接用其孩子替换待删除结点的位置
			if (Objects.nonNull(node.leftChild) && Objects.nonNull(node.rightChild)) {
				// 找到右子树最左节点,该节点最多有一个孩子
				// 摘除右子树最左节点
				// 用右子树最左节点替换待删除结点的位置
				// 返回右子树最左节点,用以在递归中保证树的逻辑结构
				Node<K, V> leftmostNodeOfRightSubtree = findMin(node.rightChild);
				// 通过node.rightChild = remove在递归中来维护树的逻辑结构
				node.rightChild = remove(leftmostNodeOfRightSubtree.key, node.rightChild);
				// 递归返回的时候,node.parent会完成与leftMostOfSubtree的左孩子或有孩子关系
				// 三个节点六条边,所以只需要处理五条边
				leftmostNodeOfRightSubtree.parent = node.parent;
				leftmostNodeOfRightSubtree.leftChild = node.leftChild;
				leftmostNodeOfRightSubtree.rightChild = node.rightChild;
				if (Objects.nonNull(node.leftChild))
					node.leftChild.parent = leftmostNodeOfRightSubtree;
				node.leftChild = null;
				if (Objects.nonNull(node.rightChild))
					node.rightChild.parent = leftmostNodeOfRightSubtree;
				node.rightChild = null;
				node = leftmostNodeOfRightSubtree;
			} else {
				// 用待删除结点的孩子替换其位置之后,为了在递归中维护树的逻辑结构,递归返回的是当前该位置的节点,即代替其位置的子节点
				// 所以在这个case中,用returnNode变量来记录替换待删除结点孩子,以便稍后递归返回该节点
				Node<K, V> returnNode = null;
				if (Objects.nonNull(node.leftChild)) {
					returnNode = node.leftChild;
					node.leftChild.parent = node.parent;
					node.leftChild = null;
				} else if (Objects.nonNull(node.rightChild)) {
					returnNode = node.rightChild;
					node.rightChild.parent = node.parent;
					node.rightChild = null;
				}
				node.parent = null;
				node = returnNode;
			}
		}
		return node;
	}

	private Node<K, V> findMin(Node<K, V> node) {
		if (Objects.isNull(node))
			throw new NullPointerException();
		Node<K, V> find = node;
		while (Objects.nonNull(find)) {
			node = find;
			find = find.leftChild;
		}
		return node;
	}
}

2.测试用例

insert构建的二叉查找树如下图所示:

插入测试:

		BinarySearchTree<Integer, String> binaryTree = new BinarySearchTree<Integer, String>();
		binaryTree.insert(62, "62");
		binaryTree.insert(58, "58");
		binaryTree.insert(88, "88");
		binaryTree.insert(47, "47");
		binaryTree.insert(73, "73");
		binaryTree.insert(99, "99");
		binaryTree.insert(35, "35");
		binaryTree.insert(51, "51");
		binaryTree.insert(93, "93");
		binaryTree.insert(37, "37");
		
		System.out.print("先序遍历:");
		TraversalTreeTool.preorderTraversalByRecursion(binaryTree.getRoot());
		System.out.println();
		System.out.print("中序遍历:");
		TraversalTreeTool.inorderTraversalByRecursion(binaryTree.getRoot());
		System.out.println();
		System.out.print("后序遍历:");
		TraversalTreeTool.postorderTraversalByRecursion(binaryTree.getRoot());
		System.out.println();
		System.out.print("层序遍历:");
		TraversalTreeTool.levelTraversal(binaryTree.getRoot());

先序遍历:62:62  58:58  47:47  35:35  37:37  51:51  88:88  73:73  99:99  93:93  
中序遍历:35:35  37:37  47:47  51:51  58:58  62:62  73:73  88:88  93:93  99:99  
后序遍历:37:37  35:35  51:51  47:47  58:58  73:73  93:93  99:99  88:88  62:62  
层序遍历:62:62  58:58  88:88  47:47  73:73  99:99  35:35  51:51  93:93  37:37  

查找测试:

		BinarySearchTree<Integer, String> binaryTree = new BinarySearchTree<Integer, String>();
		binaryTree.insert(62, "62");
		binaryTree.insert(58, "58");
		binaryTree.insert(88, "88");
		binaryTree.insert(47, "47");
		binaryTree.insert(73, "73");
		binaryTree.insert(99, "99");
		binaryTree.insert(35, "35");
		binaryTree.insert(51, "51");
		binaryTree.insert(93, "93");
		binaryTree.insert(37, "37");
		
		System.out.println(binaryTree.getRoot());
		System.out.println(binaryTree.select(62));
		System.out.println(binaryTree.select(58));
		System.out.println(binaryTree.select(88));
		System.out.println(binaryTree.select(93));
        System.out.println("查询不存在的节点:" + binaryTree.select(-1));

62:62 
62
58
88
93
查询不存在的节点:null

删除测试:

		BinarySearchTree<Integer, String> binaryTree = new BinarySearchTree<Integer, String>();
		binaryTree.insert(62, "62");
		binaryTree.insert(58, "58");
		binaryTree.insert(88, "88");
		binaryTree.insert(47, "47");
		binaryTree.insert(73, "73");
		binaryTree.insert(99, "99");
		binaryTree.insert(35, "35");
		binaryTree.insert(51, "51");
		binaryTree.insert(93, "93");
		binaryTree.insert(37, "37");
		
		System.out.print("删除不存在的节点-1:  ");
		binaryTree.remove(-1);
		TraversalTreeTool.levelTraversal(binaryTree.getRoot());
		System.out.println();
		System.out.print("删除叶节点37: ");
		binaryTree.remove(37);
		TraversalTreeTool.levelTraversal(binaryTree.getRoot());
		System.out.println();
		System.out.print("删除一个孩子节点58: ");
		binaryTree.remove(58);
		TraversalTreeTool.levelTraversal(binaryTree.getRoot());
		System.out.println();
		System.out.print("删除两个孩子节点88: ");
		binaryTree.remove(88);
		TraversalTreeTool.levelTraversal(binaryTree.getRoot());
		System.out.println();
		System.out.print("删除根节点62: ");
		binaryTree.remove(62);
		TraversalTreeTool.levelTraversal(binaryTree.getRoot());

删除不存在的节点-1:  62:62  58:58  88:88  47:47  73:73  99:99  35:35  51:51  93:93  37:37  
删除叶节点37: 62:62  58:58  88:88  47:47  73:73  99:99  35:35  51:51  93:93  
删除一个孩子节点58: 62:62  47:47  88:88  35:35  51:51  73:73  99:99  93:93  
删除两个孩子节点88: 62:62  47:47  93:93  35:35  51:51  73:73  99:99  
删除根节点62: 73:73  47:47  93:93  35:35  51:51  99:99  

 


三、非递归实现

1.实现代码

package cn.wxy.blog;

import java.util.Objects;
import cn.wxy.blog.TraversalTreeTool.TreeNode;

/**
 * 二叉查找树的非递归实现
 * 和递归实现的最大区别是逻辑结构的维护:
 * a.递归实现是在每次递归的代码部分来维护树的逻辑结构;
 * b.非递归实现需要在增、删操作中来维护树的逻辑结构和根节点;
 * @author 王大锤
 * @date 2021年6月12日
 */
public class BinarySearchTreeNonRecursive<K extends Comparable<K>, V> {
	static class Node<K extends Comparable<K>, V> implements TreeNode<K, Node<K, V>> {
		private K key;
		private V value;
		private Node<K, V> parent;
		private Node<K, V> leftChild;
		private Node<K, V> rightChild;

		public Node(K key, V value, Node<K, V> parent) {
			this.key = key;
			this.value = value;
			this.parent = parent;
		}

		public K getKey() {
			return key;
		}

		public void setKey(K key) {
			this.key = key;
		}

		public Node<K, V> getParent() {
			return parent;
		}

		public void setParent(Node<K, V> parent) {
			this.parent = parent;
		}

		public Node<K, V> getLeftChild() {
			return leftChild;
		}

		public void setLeftChild(Node<K, V> leftChild) {
			this.leftChild = leftChild;
		}

		public Node<K, V> getRightChild() {
			return rightChild;
		}

		public void setRightChild(Node<K, V> rightChild) {
			this.rightChild = rightChild;
		}

		@Override
		public String toString() {
			return this.key + ":" + value + " ";
		}
	}

	private Node<K, V> root;

	public BinarySearchTreeNonRecursive() {
	}

	public Node<K, V> getRoot() {
		return this.root;
	}

	public Node<K, V> select(K key) {
		Node<K, V> node = selectNode(key);
		if (Objects.nonNull(node) && key.compareTo(node.key) == 0)
			return node;
		return null;
	}

	/**
	 * select和insert中都需要查找结点,但是又有一些差异,所以抽取相同部分到selectNode函数中
	 * select: 从根节点开始往下找,找到返回节点,否则返回null
	 * insert: 从根节点开始往下找,找到节点更新其value,否则找到最后一个叶节点,新节点挂到叶节点的左孩子或右孩子
	 * 所以selectNode函数的逻辑:
	 * 1.从根节点开始往下找,找到则返回节点;
	 * 2.否则返回查找时最后一个叶节点;
	 * 3.如果key为null或者查找的是一颗空树,则返回null;
	 * @param key
	 * @return
	 */
	private Node<K, V> selectNode(K key) {
		if (Objects.isNull(key))
			return null;
		Node<K, V> current = null;
		Node<K, V> find = this.root;
		while (Objects.nonNull(find)) {
			// 当循环到叶子节点的时候,current等于叶子节点
			// find在接下来的判断中变为叶子节点的左孩子或右孩子,此时find一定为null,从而结束循环
			current = find;
			int compare = key.compareTo(find.key);
			if (compare < 0)
				find = find.leftChild;
			else if (compare > 0)
				find = find.rightChild;
			else
				return current;
		}
		return current;
	}

	/**
	 * 1.如果是空树,则插入的KV作为根节点;
	 * 2.如果树非空,分为两种情况
	 * a.树中已经存在key的节点,那么更新该节点的value并返回
	 * b.树中不存在key的节点,将新节点插入最后一次查找时的叶节点,作为其左孩子或右孩子
	 * @param key
	 * @param value
	 * @return
	 */
	public Node<K, V> insert(K key, V value) {
		if (Objects.isNull(key))
			throw new NullPointerException();
		// 根节点null,说明是空树
		if (Objects.isNull(this.root)) {
			this.root = new Node<K, V>(key, value, null);
			return this.root;
		}
		// 如果树非空,那selectNode的返回值要么是最后一次查找的叶节点,要么是树中已经存在同key的节点
		Node<K, V> current = selectNode(key);
		int compare = key.compareTo(current.key);
		// 如果树中已经存在同key的节点,那么修改该节点的value并返回
		if (compare == 0) {
			current.value = value;
			return current;
		}
		// 否则,current就是最后一次查找的叶节点,新节点作为该叶节点的左孩子或右孩子
		Node<K, V> node = new Node<K, V>(key, value, current);
		if (compare < 0)
			current.leftChild = node;
		else
			current.rightChild = node;
		return node;
	}

	/**
	 * 分成两种情况:
	 * 1.待删除节点有两个孩子,选取右子树最左节点替换该节点
	 * 2.待删除节点最多只有一个孩子,直接将子节点替换该节点
	 * 最后还需要判断待删除结点是不是根节点,如果是,则要将this.root指向替换节点
	 * @param key
	 * @return
	 */
	public Node<K, V> remove(K key) {
		if (Objects.isNull(key))
			return null;
		Node<K, V> deleteNode = selectNode(key);
		// 如果树是一棵空树或树中不存在要删除的key,返回null
		if (Objects.isNull(deleteNode) || key.compareTo(deleteNode.key) != 0)
			return null;
		// 到这里,deleteNode确定就是待删除的节点,接下来判断其孩子情况做进一步的处理
		if (Objects.nonNull(deleteNode.leftChild) && Objects.nonNull(deleteNode.rightChild)) {
			// deleteNode有两个孩子
			twoChildren(deleteNode);
		} else {
			// deleteNode最多有一个孩子
			oneChildAtMost(deleteNode);
		}
		return deleteNode;
	}

	private Node<K, V> findMin(Node<K, V> node) {
		if (Objects.isNull(node))
			throw new NullPointerException();
		Node<K, V> find = node;
		while (Objects.nonNull(find)) {
			node = find;
			find = find.leftChild;
		}
		return node;
	}

	/**
	 * 删除节点时,待删除结点最多只有一个孩子的情况
	 * Note:当待删除节点有两个孩子的时候,需要找到其右子树的最左节点来替代它,此时要摘除其右子树最左节点,而右子树最左节点要么是一个叶节点,要么只有一个右孩子
	 * @param deleteNode
	 */
	private void oneChildAtMost(Node<K, V> deleteNode) {
		// 需要关注deleteNode是否是根节点,如果是,那么需要修改this.root的引用指向替换节点
		Node<K, V> replaceNode = null;
		if (Objects.nonNull(deleteNode.leftChild)) {
			deleteNode.leftChild.parent = deleteNode.parent;
			if (Objects.nonNull(deleteNode.parent)) {
				if (deleteNode.equals(deleteNode.parent.leftChild))
					deleteNode.parent.leftChild = deleteNode.leftChild;
				else
					deleteNode.parent.rightChild = deleteNode.leftChild;
			}
			replaceNode = deleteNode.leftChild;
			deleteNode.leftChild = null;
		} else if (Objects.nonNull(deleteNode.rightChild)) {
			deleteNode.rightChild.parent = deleteNode.parent;
			if (Objects.nonNull(deleteNode.parent)) {
				if (deleteNode.equals(deleteNode.parent.leftChild))
					deleteNode.parent.leftChild = deleteNode.rightChild;
				else
					deleteNode.parent.rightChild = deleteNode.rightChild;
			}
			replaceNode = deleteNode.rightChild;
			deleteNode.rightChild = null;
		} else {
			if (Objects.nonNull(deleteNode.parent)) {
				if (deleteNode.equals(deleteNode.parent.leftChild))
					deleteNode.parent.leftChild = null;
				else
					deleteNode.parent.rightChild = null;
			}
		}
		deleteNode.parent = null;
		// 如果删除的是根节点,那么this.root要指向替换节点
		if (this.root.equals(deleteNode))
			this.root = replaceNode;
	}

	private void twoChildren(Node<K, V> deleteNode) {
		// deleteNode有两个孩子,找到其右子树最左节点进行替换,此时leftmostNodeOfRightSubtree要么是叶节点要么只有右孩子
		Node<K, V> leftmostNodeOfRightSubtree = findMin(deleteNode.rightChild);
		// 摘除leftmostNodeOfRightSubtree
		oneChildAtMost(leftmostNodeOfRightSubtree);
		// 将leftmostNodeOfRightSubtree替换deleteNode的位置:
		// 1.处理父节点关系
		leftmostNodeOfRightSubtree.parent = deleteNode.parent;
		if (Objects.nonNull(deleteNode.parent)) {
			if (deleteNode.equals(deleteNode.parent.leftChild))
				deleteNode.parent.leftChild = leftmostNodeOfRightSubtree;
			else
				deleteNode.parent.rightChild = leftmostNodeOfRightSubtree;
		}
		deleteNode.parent = null;
		// 虽然node的左右子树非空,但是如果左右子树都只有一个节点,那么oneChildAtMost方法调用完成之后,其左孩子或右孩子变成了null
		// 2.处理左孩子
		leftmostNodeOfRightSubtree.leftChild = deleteNode.leftChild;
		if (Objects.nonNull(deleteNode.leftChild))
			deleteNode.leftChild.parent = leftmostNodeOfRightSubtree;
		deleteNode.leftChild = null;
		// 3.处理右孩子
		leftmostNodeOfRightSubtree.rightChild = deleteNode.rightChild;
		if (Objects.nonNull(deleteNode.rightChild))
			deleteNode.rightChild.parent = leftmostNodeOfRightSubtree;
		deleteNode.rightChild = null;
		// 如果删除的是根节点,那么this.root要指向替换节点
		if (this.root.equals(deleteNode))
			this.root = leftmostNodeOfRightSubtree;
	}
}

2.测试用例

insert构建的二叉查找树如下图所示:

插入测试:

		BinarySearchTreeNonRecursive<Integer, String> binaryTree = new BinarySearchTreeNonRecursive<Integer, String>();
		binaryTree.insert(62, "62");
		binaryTree.insert(58, "58");
		binaryTree.insert(88, "88");
		binaryTree.insert(47, "47");
		binaryTree.insert(73, "73");
		binaryTree.insert(99, "99");
		binaryTree.insert(35, "35");
		binaryTree.insert(51, "51");
		binaryTree.insert(93, "93");
		binaryTree.insert(37, "37");

		System.out.print("先序遍历:");
		TraversalTreeTool.preorderTraversalByRecursion(binaryTree.getRoot());
		System.out.println();
		System.out.print("中序遍历:");
		TraversalTreeTool.inorderTraversalByRecursion(binaryTree.getRoot());
		System.out.println();
		System.out.print("后序遍历:");
		TraversalTreeTool.postorderTraversalByRecursion(binaryTree.getRoot());
		System.out.println();
		System.out.print("层序遍历:");
		TraversalTreeTool.levelTraversal(binaryTree.getRoot());

先序遍历:62:62  58:58  47:47  35:35  37:37  51:51  88:88  73:73  99:99  93:93  
中序遍历:35:35  37:37  47:47  51:51  58:58  62:62  73:73  88:88  93:93  99:99  
后序遍历:37:37  35:35  51:51  47:47  58:58  73:73  93:93  99:99  88:88  62:62  
层序遍历:62:62  58:58  88:88  47:47  73:73  99:99  35:35  51:51  93:93  37:37  

查询测试:

		BinarySearchTreeNonRecursive<Integer, String> binaryTree = new BinarySearchTreeNonRecursive<Integer, String>();
		binaryTree.insert(62, "62");
		binaryTree.insert(58, "58");
		binaryTree.insert(88, "88");
		binaryTree.insert(47, "47");
		binaryTree.insert(73, "73");
		binaryTree.insert(99, "99");
		binaryTree.insert(35, "35");
		binaryTree.insert(51, "51");
		binaryTree.insert(93, "93");
		binaryTree.insert(37, "37");

		System.out.println(binaryTree.getRoot());
		System.out.println(binaryTree.select(62));
		System.out.println(binaryTree.select(58));
		System.out.println(binaryTree.select(88));
		System.out.println(binaryTree.select(93));
		System.out.println("查询不存在的节点:" + binaryTree.select(-1));

62:62 
62:62 
58:58 
88:88 
93:93 
查询不存在的节点:null

删除测试:

		BinarySearchTreeNonRecursive<Integer, String> binaryTree = new BinarySearchTreeNonRecursive<Integer, String>();
		binaryTree.insert(62, "62");
		binaryTree.insert(58, "58");
		binaryTree.insert(88, "88");
		binaryTree.insert(47, "47");
		binaryTree.insert(73, "73");
		binaryTree.insert(99, "99");
		binaryTree.insert(35, "35");
		binaryTree.insert(51, "51");
		binaryTree.insert(93, "93");
		binaryTree.insert(37, "37");

		System.out.print("删除不存在的节点-1:  ");
		binaryTree.remove(-1);
		TraversalTreeTool.levelTraversal(binaryTree.getRoot());
		System.out.println();
		System.out.print("删除叶节点37: ");
		binaryTree.remove(37);
		TraversalTreeTool.levelTraversal(binaryTree.getRoot());
		System.out.println();
		System.out.print("删除一个孩子节点58: ");
		binaryTree.remove(58);
		TraversalTreeTool.levelTraversal(binaryTree.getRoot());
		System.out.println();
		System.out.print("删除两个孩子节点88: ");
		binaryTree.remove(88);
		TraversalTreeTool.levelTraversal(binaryTree.getRoot());
		System.out.println();
		System.out.print("删除根节点62: ");
		binaryTree.remove(62);
		TraversalTreeTool.levelTraversal(binaryTree.getRoot());

删除不存在的节点-1:  62:62  58:58  88:88  47:47  73:73  99:99  35:35  51:51  93:93  37:37  
删除叶节点37: 62:62  58:58  88:88  47:47  73:73  99:99  35:35  51:51  93:93  
删除一个孩子节点58: 62:62  47:47  88:88  35:35  51:51  73:73  99:99  93:93  
删除两个孩子节点88: 62:62  47:47  93:93  35:35  51:51  73:73  99:99  
删除根节点62: 73:73  47:47  93:93  35:35  51:51  99:99  

 


参考资料:

标签:node,insert,deleteNode,tree,binaryTree,二叉,查找,key,节点
来源: https://blog.csdn.net/reliveIT/article/details/117710589