排序二叉树及其Java实现

定义

排序二叉树的定义也是递归定义的,需要满足:

(1)若它的左子树不为空,则左子树上所有节点的值要均小于根节点的值;

(2)若它的右子树不为空,则右子树上所有节点的值要均大于根节点的值;

(3)左、右子树也分别是排序二叉树

如下图,对于排序二叉树,若按中序遍历就可以得到由小到大的有序序列。

创建

创建排序二叉树的步骤就是不断像排序二叉树中添加新节点(p)的过程:

(1)以根节点(root)为当前节点(current)开始搜索;

(2)用新节点p的值和current的值进行比较;

(3)如果p.data>current.data,则current=current.right;若p.data<current.data,则current=current.left;

(4)重复(2)(3),直到找到合适的叶子节点位置;

(5)将p添加到上面找到的合适位置,若新节点更大,则添加为右子节点;否则,加为左子节点

删除节点

当从排序二叉树中删除节点后,要保持它依然是二叉树,必须对它进行维护:

待删除节点p,p的父节点q,p的左子树pL,p的右子树pR

(1·)p是叶子节点,直接将它从其父节点中删除;

(2)p只有左(右)子树,将pL(pR)添加成p的父节点q的左(右)子树即可;

(3)p左右子树均非空,有两种处理方法:

  • 将pL设为q的左或右子节点(取决于p是其父节点q的左、右子节点),将pR设为p的中序前驱结点s的右子节点(s是pL最右下的节点,也就是pL中最大的节点)
  • 以p的中序前驱或后继替代p所指节点,然后再从原排序二叉树中删去中序前驱或后继节点(也就是用大于p的最小节点或小于p的最大节点代替p节点)

Java实现代码:

package com.liuhao.DataStructures;

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


public class SortedBinTree <T extends Comparable>{

	static class Node{
		Object data;
		Node parent;
		Node left;
		Node right;
		
		public Node(Object data, Node parent, Node left, Node right) {
			this.data = data;
			this.parent = parent;
			this.left = left;
			this.right = right;
		}
		
		public String toString(){
			return "[data=" + data + "]";
		}
		
		public boolean equals(Object obj){
			if(this == obj){
				return true;
			}
			
			if(obj.getClass() == Node.class){
				Node target = (Node) obj;
				return data.equals(target.data) && left == target.left 
						&& right == target.right && parent == target.parent;
			}
			
			return false;
		}
		
	}
	
	private Node root;
	
	public SortedBinTree(){
		root = null;
	}	
	
	public SortedBinTree(T o){
		root = new Node(o, null, null, null);
	}
	
	/**
	 * 添加节点
	 * @param ele 新节点的元素
	 */
	public void add(T ele){
		if(root == null){
			root = new Node(ele, null, null, null);
		}
		else{
			Node current = root;
			Node parent = null;
			int cmp;
			
			//搜索合适的叶子节点,以该叶子节点为父节点添加新节点
			do{
				parent = current;
				cmp = ele.compareTo(current.data);
				
				//如果新节点的值大于当前节点的值
				if(cmp > 0){
					//以当前节点的右子节点作为当前节点
					current = current.right;
				}else{
					current = current.left;
				}
			}while(current != null);
			
			//创建新节点
			Node newNode = new Node(ele, parent, null, null);
			
			//如果新节点的值大于父节点的值
			if(cmp > 0){
				parent.right = newNode;
			}else{
				parent.left = newNode;
			}
		}
	}
	
	/**
	 * 删除节点
	 * @param ele
	 */
	public void remove(T ele){
		Node target = getNode(ele);
		
		if(target == null){
			return;
		}
		
		//左右子树都为空
		if(target.left == null && target.right == null){
			if(target == root){
				root = null;
			}
			else{
				//被删除节点是父节点的左子节点
				if(target == target.parent.left){
					//将target的父节点的left设为null
					target.parent.left = null;
				}else{
					target.parent.right = null;
				}
				
				target.parent = null;
			}
		}
		
		//左空右不空
		else if(target.left == null && target.right != null){
			if(target == root){
				root = target.right;
			}
			else{
				//被删除节点是父节点的左子节点
				if(target == target.parent.left){
					target.parent.left = target.right;
				}
				else{
					target.parent.right = target.right;
				}
				
				//让target的右子树的parent指向target的parent
				target.right.parent = target.parent;
			}
		}
		
		else if(target.left != null && target.right == null){
			if(target == root){
				root = target.left;
			}
			else{
				//被删除节点是父节点的左子节点
				if(target == target.parent.left){
					target.parent.left = target.left;
				}
				else{
					target.parent.right = target.left;
				}
				
				//让target的右子树的parent指向target的parent
				target.left.parent = target.parent;
			}
		}
		
		//左右都不为空
		else{
			//leftMaxNode:target的左子树中值最大的节点
			Node leftMaxNode = target.left;
			
			//搜索target的左子树中值最大的节点
			while(leftMaxNode.right != null){
				leftMaxNode = leftMaxNode.right;
			}
			
			//从原来的子树中删除leftMaxNode节点
			leftMaxNode.parent.right = null;
			
			leftMaxNode.parent = target.parent;
			
			if(target == target.parent.left){
				target.parent.left = leftMaxNode;
			}
			else{
				target.parent.right = leftMaxNode;
			}
			
			leftMaxNode.left = target.left;
			leftMaxNode.right = target.right;
			target.parent = target.left = target.right = null;
		}
	}
	
	/**
	 * 根据指定值搜索节点
	 * @param ele 指定值
	 * @return 节点
	 */
	public Node getNode(T ele){
		//从根节点开始搜索
		Node p = root;
		while(p != null){
			int cmp = ele.compareTo(p.data);
			
			if(cmp < 0){
				p = p.left;
			}
			else if(cmp > 0){
				p = p.right;
			}
			else{
				return p;
			}
		}
		
		return null;
	}
	
	/**
	 * 广度优先遍历
	 * @return
	 */
	public List<Node> breadthFirst(){
		Queue<Node> queue = new ArrayDeque<Node>();
		List<Node> list = new ArrayList<Node>();
		
		if(root != null){
			queue.offer(root);
		}
		
		while(!queue.isEmpty()){
			//将该队列的“队尾”元素添加到List中
			list.add(queue.peek());
			//弹出队尾节点
			Node p = queue.poll();
			
			//如果左子节点不为null,将它加入“队列”
			if(p.left != null){
				queue.offer(p.left);
			}
			
			if(p.right != null){
				queue.offer(p.right);
			}
		}
		
		return list;
	}
	
	/**
	 * 中序遍历
	 * @return
	 */
	public List<Node> inIterator(){
		return inIterator(root);
	}
	
	private List<Node> inIterator(Node node){
		List<Node> list = new ArrayList<Node>();
		
		//递归处理左子树
		if(node.left != null){
			list.addAll(inIterator(node.left));
		}
		
		//处理根节点
		list.add(node);
		
		//递归处理右子树
		if(node.right != null){
			list.addAll(inIterator(node.right));
		}
		
		return list;
	}
}


排序二叉树及其Java实现,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。