数据结构查找二叉树SearchBinaryTree之JAVA代码

Posted by Naah on Thursday, Aug 17,2017 11:00:26

下面是我自己写的查找二叉树的结构:

希望对各位有所帮助,如果有错误的地方或更好的建议,请不吝赐教,谢谢

  1. 构建查找二叉树
  2. 查找二叉树添加节点方法
  3. 在某树找到距离该数据最近的节点
  4. 查找二叉树节点
  5. 得到最小数据节点方法
  6. 移除节点方法
  7. 递归查询二叉树中序遍历(从小到大排列)

/**
 *
 * 2017年8月11日 上午10:18:08
 *
 */
public class SearchBinaryTree> {
	public TreeEntry root;

	/**
	 * 构建查找二叉树
	 * @param a
	 */
	public void newSearchBinaryTree(T... a) {
		for (T t : a) {
			put(t);
		}
	}

	/**
	 * 查找二叉树添加节点方法
	 * @param data 数据
	 * @return 数据的节点
	 */
	public TreeEntry put(T data) {

		// 如果根节点为空,
		if (root == null) {

			// 则将该节点设置为根节点
			root = new TreeEntry<>(data);
			return null;
		}

		// 找到最近的节点作为父节点
		TreeEntry parent = getRecentlyNode(data, root);
		if (parent.data.equals(data)) {
			return parent;
		}
		// 为当前数据创建新节点
		TreeEntry node = new TreeEntry<>(data);

		// 如果当前数据小于父节点数据
		if (data.compareTo(parent.data) == -1) {

			// 将当前节点设置为父节点的左孩子节点
			parent.leftChild = node;

			// 如果当前数据大于父节点数据
		} else if (data.compareTo(parent.data) == 1) {

			// 将当前节点设置为父节点的右孩子节点
			parent.rightChild = node;
		}

		// 将父节点设置为当前数据的父节点
		node.parent = parent;

		// 返回当前节点
		return node;

	}

	/**
	 * 在该树中找到距离该数据最近的节点
	 * @param data 数据
	 * @param tree 树
	 * @return 节点
	 */
	public TreeEntry getRecentlyNode(T data, TreeEntry tree) {
		// 设置节点变量,与父节点变量
		TreeEntry node, parent = null;

		// 将根节点设置为当前节点
		node = tree;

		// 当前节点不为空时继续循环
		while (node != null) {

			// 将当前节点设置为父节点,准备递归子树
			// 为添加新节点做缓存
			parent = node;

			// 如果新数据小于当前节点数据
			if (data.compareTo(node.data) == -1) {

				// 将当前节点设置为左孩子节点,进行递归左子树
				node = node.leftChild;

				// 如果新数据大于当前节点数据
			} else if (data.compareTo(node.data) == 1) {

				// 将当前节点设置为右孩子节点,进行递归右子树
				node = node.rightChild;

				// 如果新数据等于当前节点数据
			} else {

				// 返回当前节点
				return node;
			}

		}
		return parent;
	}

	/**
	 * 非递归查找
	 * @param data 数据
	 * @return 节点
	 */
	public TreeEntry nonRecSearch(T data) {
		if (root == null) {
			return null;
		}
		TreeEntry node = root;
		while (node != null) {
			// 如果新数据小于当前节点数据
			if (data.compareTo(node.data) == -1) {

				// 将当前节点设置为左孩子节点,进行递归左子树
				node = node.leftChild;

				// 如果新数据大于当前节点数据
			} else if (data.compareTo(node.data) == 1) {

				// 将当前节点设置为右孩子节点,进行递归右子树
				node = node.rightChild;

				// 如果新数据等于当前节点数据
			} else {

				// 返回当前节点
				return node;
			}

		}
		return null;
	}

	/**
	 * 递归查询节点方法
	 * @param data
	 * @return
	 */
	public TreeEntry recSearch(T data) {
		return recSearch(data, root);
	}

	/**
	 * 二叉树递归查询节点方法
	 * @param data 数据
	 * @param tree 树
	 * @return 节点
	 */
	private TreeEntry recSearch(T data, TreeEntry tree) {
		// 如果该树根节点为空,则返回空
		if (tree == null) {
			return null;
		}

		// 判断数据与根节点数据的大小
		switch (data.compareTo(tree.data)) {

		// 数据>根节点数据
		case 1:

			// 递归根节点的右子树
			return recSearch(data, tree.rightChild);

			// 数据<根节点数据
		case -1:

			// 递归根节点的左子树
			return recSearch(data, tree.leftChild);

			// 相等
		case 0:

			// 返回根节点
			return tree;

			// 没找到返回空
		default:
			return null;
		}
	}

	/**
	 * 节点覆盖方法
	 * @param node 原节点
	 * @param newNode 新节点
	 */
	private void replaceNode(TreeEntry node, TreeEntry newNode) {

		// 获取原节点的父节点
		TreeEntry parent = node.parent;

		// 如果原节点为父节点的左孩子
		if (node.equals(parent.leftChild)) {

			// 将新节点作为父节点的左孩子
			parent.leftChild = newNode;

			// 否则原节点为父节点的右孩子
		} else {

			// 将新节点作为父节点的右孩子
			parent.rightChild = newNode;
		}
	}

	/**
	 * 最小节点方法
	 * @return 最小节点
	 */
	public TreeEntry getMin() {
		return findMin(root);
	}

	/**
	 * 树中最小节点方法
	 * @param tree 树
	 * @return 最小节点
	 */
	private TreeEntry findMin(TreeEntry tree) {

		// 如果该节点为空,则返回空
		if (tree == null) {
			return null;
		}

		// 如果该节点有左子树
		if (tree.leftChild != null) {

			// 递归左子树
			return findMin(tree.leftChild);

			// 否则没有左子树,返回该节点
		} else {
			return tree;
		}
	}

	/**
	 * 移除节点
	 * @param data 数据
	 * @return 节点
	 */
	public TreeEntry remove(T data) {
		return remove(data, root);
	}

	/**
	 * 树中移除节点方法
	 * @param data 数据
	 * @return 节点
	 */
	public TreeEntry remove(T data, TreeEntry tree) {

		// 在树中搜索该节点
		TreeEntry node = recSearch(data, tree);

		// 如果没有找到该节点返回空
		if (node == null) {
			return null;
		}

		// 获取该节点的父节点
		TreeEntry parent = node.parent;

		// 获取该节点的左孩子节点
		TreeEntry leftChild = node.leftChild;

		// 获取该节点的右孩子节点
		TreeEntry rightChild = node.rightChild;

		// 如果两个节点都不为空
		if (leftChild != null && rightChild != null) {

			// 获取该节点的右子树中最小的,并取出其中数据
			T min = findMin(rightChild).data;

			// 在右子树中移除该最小节点
			if (remove(min, rightChild) == null) {
				throw new RuntimeException("删除错误");
			}

			// 见最小元素构建为新节点
			TreeEntry newNode = new TreeEntry<>(min);

			// 将原节点的引用复制到新节点上
			newNode.parent = parent;
			newNode.leftChild = leftChild;
			newNode.rightChild = rightChild;
			leftChild.parent = newNode;
			rightChild.parent = newNode;

			// 如果原节点为根节点
			if (node == root) {

				// 将新节点作为根节点
				root = newNode;

				// 否则用心节点覆盖到老节点
			} else {
				replaceNode(node, newNode);
			}
		} else {

			// 如果该节点为根节点
			if (node == root) {

				// 如果根节点为叶子节点
				if (leftChild == null && rightChild == null) {
					// 将根节点设置为空
					root = null;

					// 如果左孩子节点为空
				} else if (leftChild == null) {

					// 使用右孩子节点覆盖根节点
					root = rightChild;

					// 该节点父节点为空
					rightChild.parent = null;

					// 如果该节点得右孩子节点为空
				} else {

					// 使用左孩子节点覆盖根节点
					root = leftChild;

					// 该节点的父节点为空
					leftChild.parent = null;
				}

				// 如果该节点不为根节点
			} else {

				// 如果该节点为叶子节点
				if (leftChild == null && rightChild == null) {

					// 使用空覆盖该节点的孩子节点
					replaceNode(node, null);

					// 如果该节点的左孩子节点为空
				} else if (leftChild == null) {

					// 用右孩子节点覆盖原节点
					replaceNode(node, rightChild);

					// 如果该节点的右孩子节点为空
				} else {

					// 用左孩子节点覆盖原节点
					replaceNode(node, leftChild);
				}
			}

		}

		return node;
	}

	public void midOrder() {
		midOrder(root);
	}

	/**
	 * 递归二叉树中序遍历方法
	 * @param tree
	 */
	private void midOrder(TreeEntry tree) {
		// 如果节点为空,则返回
		if (tree == null) {
			return;
		} else {

			// 中序遍历的顺序为,左根右

			// 中序遍历左子树
			midOrder(tree.leftChild);

			// 输出根节点
			System.out.println(tree.data);

			// 中序遍历右子树
			midOrder(tree.rightChild);
		}
	}

	public class TreeEntry {
		private int index;
		private T data;
		private TreeEntry parent;
		private TreeEntry leftChild;
		private TreeEntry rightChild;

		public TreeEntry(int index) {
			super();
			this.index = index;
		}

		public TreeEntry(T data) {
			super();
			this.data = data;
		}

		public TreeEntry(int index, T data) {
			super();
			this.index = index;
			this.data = data;
		}

		public int getIndex() {
			return index;
		}

		public void setIndex(int index) {
			this.index = index;
		}

		public T getData() {
			return data;
		}

		public void setData(T data) {
			this.data = data;
		}

		public TreeEntry getLeftChild() {
			return leftChild;
		}

		public void setLeftChild(TreeEntry leftChild) {
			this.leftChild = leftChild;
		}

		public TreeEntry getRightChild() {
			return rightChild;
		}

		public void setRightChild(TreeEntry rightChild) {
			this.rightChild = rightChild;
		}

		public TreeEntry getParent() {
			return parent;
		}

		public void setParent(TreeEntry parent) {
			this.parent = parent;
		}

		@Override
		public String toString() {
			return data.toString();
		}

	}
}