Java基础复习笔记10数据结构-排序二叉树

1.       排序二叉树

排序二叉树是在二叉树的限制基础上又加了一些限制,所有的的树节点数据都具有可比较性质、树的根节点数据肯定都大于它的左子树中所有节点、树的根节点数据也都小于或者等于它的右子树的所有节点。同理这个棵树上的父节点都大于左节点,并且小于等于右节点。如下图所示。

 

就是一颗排序二叉树,对此树进行深度优先中根遍历法,那么会得到从小到大的排列顺序:12457101213141518

2.       使用场景

顾名思义,排序二叉树就是为了快速排序,查找元素时用的最多的。

3.       维护排序二叉树

构建一棵排序二叉树可能对于咱们来说不是什么难事,但是关键是维护好这颗排序二叉树。比如新增或者删除一个元素节点后,还能严格的保持这棵树是一颗排序二叉树。尤其是涉及到删除节点元素的时候,需要考虑的因素就比较多了比如删除一个节点后,得考虑这个节点是否有子节点,有几个子节点等等。

一般分为如下几个情况处理。

1):被删除的节点是叶子节点,没关系,不会影响大局,直接删除即可

2):被删节点只有左子树或者只有右子树,被删除的节点只有单子树的。直接将被删节点的子树赋给被删节点的父节点即可,也就是说被删节点的左子树代替被删节点成为被删结点父亲的左子树,而被删节点的右子树代替被删节点成为被删结点父亲的右子树。

3):被删节点既有左子树又有右字数,这种是比较麻烦的,也就是当不当、正不正只删除中间的节点。这个时候就要用被删节点最大左子树的节点或者用最小右子树的的节点代替被删节点。

添加节点:添加节点的过程实际上就是构建排序二叉树的过程。原理如下

1):首先有一个根节点

2):以根节点作为当前节点开始检索

3):新增节点和当前节点进行值比较

4):如果新节点比当前节点大,那么当前节点的右子节点作为新的当前节点,如果当前节点比当前节点小,那么当前节点的左子节点作为新的当前节点。

5):重复34步骤直到当前节点没有了子节点,那么新节点作为当前节点的子节点,具体作为左子节点还是有子节点得看新节点的值和当前节点值得比较。

4.       算法代码

实现创建排序二叉树以及维护排序二叉树的代码如下:

package dateStructer.tree.orderTree;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;

/**
 * 排序二叉树
 * 
 * @author liuyan
 */
public class OrderTree {

	static class Node {
		Integer data;
		Node parent;
		Node left;
		Node right;

		public Node(Integer data, Node parent, Node left, Node right) {

			this.data = data;
			this.parent = parent;
			this.left = left;
			this.right = right;

		}

		@Override
		public String toString() {
			return "[data:" + this.data + "]";
		}

	}

	private Node root;

	public OrderTree(Integer data) {
		root = new Node(data, null, null, null);
	}

	/**
	 * 添加新节点
	 * 
	 * @param data
	 */
	public void addNode(Integer data) {

		if (root == null) {
			root = new Node(data, null, null, null);
			return;
		}

		// 从根节点开始
		Node nowNode = root;
		Node newParent = null;
		do {
			newParent = nowNode;
			if (nowNode.data > data) {
				nowNode = nowNode.left;
			} else {
				nowNode = nowNode.right;
			}

		} while (nowNode != null);

		if (newParent.data > data) {
			newParent.left = new Node(data, newParent, null, null);
		} else {
			newParent.right = new Node(data, newParent, null, null);
		}

	}

	/**
	 * 查找节点对象
	 * 
	 * @param data
	 * @return
	 */
	public Node findNode(Integer data) {

		Node nowNode = root;

		while (nowNode != null) {

			if (nowNode.data == data) {
				return nowNode;
			}

			if (nowNode.data > data) {
				nowNode = nowNode.left;
			} else {
				nowNode = nowNode.right;
			}

		}
		return null;

	}

	/**
	 * 删除节点
	 * 
	 * @param data
	 */
	public void deleteNode(Integer data) {
		Node tagNode = findNode(data);

		if (tagNode == null) {
			return;
		}
		if (tagNode == root) {
			root = null;
		}
		if (tagNode.left == null && tagNode.right == null) {
			if (tagNode.parent.left == tagNode) {
				tagNode.parent.left = null;
			} else if (tagNode.parent.right == tagNode) {
				tagNode.parent.right = null;
			}
			return;
		}
		if (tagNode.left == null && tagNode.right != null) {
			if (tagNode.parent.left == tagNode) {
				tagNode.parent.left = tagNode.right;
			} else if (tagNode.parent.right == tagNode) {
				tagNode.parent.right = tagNode.right;
			}
			return;
		}

		if (tagNode.left != null && tagNode.right == null) {
			if (tagNode.parent.left == tagNode) {
				tagNode.parent.left = tagNode.left;
			} else if (tagNode.parent.right == tagNode) {
				tagNode.parent.right = tagNode.left;
			}
			return;
		}

		Node leftMaxNode = tagNode.left;

		while (leftMaxNode.right != null) {
			leftMaxNode = leftMaxNode.right;
		}

		leftMaxNode.parent.right = null;
		leftMaxNode.parent = tagNode.parent;

		if (tagNode == tagNode.parent.left) {
			leftMaxNode.parent.left = leftMaxNode;
		} else {
			leftMaxNode.parent.right = leftMaxNode;
		}

		leftMaxNode.left = tagNode.left;
		leftMaxNode.right = tagNode.right;
		tagNode.left = null;
		tagNode.right = null;
		tagNode.parent = null;
	}

	public static List<Node> deepFirst(Node root) {

		List<Node> list = new ArrayList<Node>();
		Queue<Node> queue = new ArrayDeque<Node>();
		queue.add(root);

		while (!queue.isEmpty()) {

			list.add(queue.peek());

			Node twoLinkNode = queue.poll();

			if (twoLinkNode.left != null) {
				queue.add(twoLinkNode.left);
			}

			if (twoLinkNode.right != null) {
				queue.add(twoLinkNode.right);
			}
		}

		return list;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		OrderTree orderTree = new OrderTree(7);
		orderTree.addNode(4);
		orderTree.addNode(1);
		orderTree.addNode(2);
		orderTree.addNode(5);
		orderTree.addNode(5);
		orderTree.addNode(13);
		orderTree.addNode(10);
		orderTree.addNode(12);
		orderTree.addNode(15);
		orderTree.addNode(14);
		orderTree.addNode(18);
		System.out.println(deepFirst(orderTree.root));
		orderTree.deleteNode(4);
		System.out.println(deepFirst(orderTree.root));
	}
}

 运行后效果如下

[[data:7], [data:4], [data:13], [data:1], [data:5], [data:10], [data:15], [data:2], [data:5], [data:12], [data:14], [data:18]]
//删除后
[[data:7], [data:2], [data:13], [data:1], [data:5], [data:10], [data:15], [data:5], [data:12], [data:14], [data:18]]

 删除后的树形图应该如下



 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值