二叉树实现

树是一个非空元素的集合,其中一个元素为根,其余元素为子树,树根是唯一没有父母的元素,相同父母的孩子是兄弟。

树的高度是指树的级的个数,元素的度是指孩子的个数,叶子节点的度为0,如图所示。

二叉树是一种特殊的树,二叉树的区别如下:

(1)二叉树的每个元素正好有两棵子树,树可以有任意棵

(2)二叉树中每个元素是有序的(左右不能互换),二树是无序的

(3)二叉树允许为空(根节点=null),树不能为空(有争议)

二叉树典型结构如图所示

有以下特性:

(1)一棵二叉树有n个元素,有n-1条边

(2)一棵二叉树的高度为h(≥0),则最少有h个元素,最多有2^h-1个元素

(3)一棵二叉树有n个元素(>0),二叉树的最大高度是n,最小高度是log2(n+1)

(4)叶子节点数目=度为2的节点数目+1

二叉树可以采用链表描述和数组描述

采用链表描述:

采用链表描述需要首先描述单个节点,每个节点需要保持的信息包括左孩子、有孩子和元素值,左孩子和右孩子可以用指针描述,代码如下:

 1 class BinaryTreeNode{
 2         public BinaryTreeNode left, right;//左子数,右子数
 3         int val;//节点元素
 4         //提供不同的初始化函数
 5         public BinaryTreeNode(){
 6             left = right = null;
 7         }
 8         public BinaryTreeNode(int val){
 9             this.val = val;
10             left = right = null;
11         }
12         public BinaryTreeNode(int val, BinaryTreeNode left, BinaryTreeNode right){
13             this.val = val;
14             this.left = left;
15             this.right = right;
16         }
17     }

然后实现二叉树的操作,二叉树需要实现的操作有元素的增删改查以及打印等信息,二叉树主要实现功能如下:

public class BinaryTree {
	private BinaryTreeNode root;
	private int treeSize; 
	
	class BinaryTreeNode{
		public BinaryTreeNode left, right;//左子数,右子数
		int val;//节点元素
		//提供不同的初始化函数
		public BinaryTreeNode(){
			left = right = null;
		}
		public BinaryTreeNode(int val){
			this.val = val;
			left = right = null;
		}
		public BinaryTreeNode(int val, BinaryTreeNode left, BinaryTreeNode right){
			this.val = val;
			this.left = left;
			this.right = right;
		}
	}
	
	//前序遍历
	public void preOrder(BinaryTreeNode binaryTreeNode){
		
	}
	
	//中序遍历
	public void inOrder(BinaryTreeNode binaryTreeNode){

	}
	
	//后续遍历
	public void postOrder(BinaryTreeNode binaryTreeNode){

	}
	
	//层次遍历
	public void levelOrder(BinaryTreeNode binaryTreeNode){
		
	}
	
	//返回节点数目
	public final int size(){
		return treeSize;
	}
	
	//检查是树否为空
	public final boolean  isEmpty()  {
		return treeSize == 0;
	}
	
	//确定二叉树的高度
	public int heightRoot(){
		
	}
	
	//查找结点
	public BinaryTreeNode find(int value){
		
		return current;
	}
	
	//增加节点
	public void insert(int value){
		
	}
	
	//查找最小值
	public int minimum(){

	}
	
	//根据值,删除节点
	public boolean delete(int value){
			
		return true;
	} 
	
}

  在所有功能中,节点的数目以及检查树是否为空代码较为简单不做叙述,其他功能实现方式如下。

前序遍历(DLR):又叫先跟遍历,属于深度优先遍历,遍历方式是根->左->右

中序遍历(LDR):又叫中跟遍历,属于深度优先遍历,遍历方式是左->根->右

后续遍历(LRD):又叫后根遍历,属于深度优先遍历,遍历方式是左->右->根

层次遍历:属于广度优先遍历,自上而下,自左向右逐层遍历节点。

各个遍历方式如下图所示:

前序遍历反映了深度优先搜索的思想,沿着二叉树的枝干从左到右游历一圈就是前序遍历,如图所示。

中序遍历能够应用在BST(Binary Sort Tree|二叉排序树)中,遍历出来的结果一定是有序的,对于一个二叉树进行垂直投影也可以得到中序遍历结果,如图所示:

此外,中序遍历还可以用于表示中缀表达式,后续遍历可以用于后缀表达式,效果如图所示:

层次遍历,层次遍历反应的是广度优先搜索思想,对于四种遍历方式,知道任意一种不能唯一的确定数据结构,如果知道中序遍历和另外任意一种遍历方式,就能够唯一的确定一棵树。

前序遍历、中序遍历和后续遍历的实现代码如下:

//前序遍历
	public void preOrder(int binaryTreeNode){
		//前序遍历二叉树
		if(binaryTreeNode >= 0 && binaryTreeNode < treeSize){
			visitTreeNode(binaryTreeNode);
			preOrder(2*binaryTreeNode+1);
			preOrder(2*binaryTreeNode+2);
		}
	}
	
	//中序遍历
	public void inOrder(int binaryTreeNode){
		//中序遍历二叉树
		if(binaryTreeNode >= 0 && binaryTreeNode < treeSize){
			inOrder(2*binaryTreeNode+1);
			visitTreeNode(binaryTreeNode);
			inOrder(2*binaryTreeNode+2);
		}
	}
	
	//后续遍历
	public void postOrder(int binaryTreeNode){
		//后续遍历二叉树
		if(binaryTreeNode >= 0 && binaryTreeNode < treeSize){
			postOrder(2*binaryTreeNode+1);
			postOrder(2*binaryTreeNode+2);
			visitTreeNode(binaryTreeNode);
		}
	}

  层次遍历的实现方式稍微复杂,层次遍历首先需要记录每一层的换行的地方,我们可以采用nlast指针始终指向最右的节点来实现,其次需要将每一层的节点依次打印,我们可以借助链表实现,整体的访问过程如下图所示:

代码实现如下:

//层次遍历
	public void levelOrder(BinaryTreeNode binaryTreeNode){
		//层次遍历二叉树
		Queue<BinaryTreeNode> nodeQueue = new LinkedList<BinaryTreeNode>();
		BinaryTreeNode last=binaryTreeNode;
		BinaryTreeNode nlast=binaryTreeNode;
		while(binaryTreeNode != null){
			visitTreeNode(binaryTreeNode);
			last = binaryTreeNode;
			//将孩子加入队列
			if(binaryTreeNode.left != null){
				nodeQueue.offer(binaryTreeNode.left);
			}
			if(binaryTreeNode.right != null){
				nodeQueue.offer(binaryTreeNode.right);
			}
			//提取下一个要访问的节点
			if(nodeQueue.isEmpty() == true){
				return;//此处可以退出循环
			}
			binaryTreeNode = nodeQueue.poll();
			if(last == nlast){
				//该层打印结束,需要换行
				System.out.println();
				if(nlast.right != null){
					nlast = nlast.right;
				}
			}
			
		}
	}

  树的高度确定只需要递归判定左右子树的高度即可,实现代码如下:

//确定二叉树的高度
	public int heightRoot(){
		return height(root);
	}
	
	private int height(BinaryTreeNode binaryTreeNode){
		int hl, hr;//左树高度,右树高度
		if(binaryTreeNode == null){
			return 0;
		}
		hl = height(binaryTreeNode.left);
		hr = height(binaryTreeNode.right);
		if(hl > hr)
			return ++hl;
		else
			return ++hr;
	}

  节点的插入:插入节点从根节点出发,如果小于根节点,就向左子树移动,与左孩子比较,如果大于根节点就向右子树移动,与有孩子比较,知道遇到空节点,放到该位置,实现代码如下:

//增加节点
	public void insert(int value){
		BinaryTreeNode node = new BinaryTreeNode(value);
		if(root == null){
			//将增加的节点设置为根节点
			root = node;
		}else{
			BinaryTreeNode current = root;
			BinaryTreeNode parent = root;
			while(current != null){
				parent = current;//记录父类信息,防止丢失父类信息
				if(value < current.val){
					current = current.left;
				}else{
					current = current.right;
				}
			}
			if(value < parent.val){
				parent.left = node;
			}else{
				parent.right = node;
			}
		}
		treeSize++;
	}

  查找最小值:根据二叉树的插入方式可以看出,该二叉树属于二叉查找树,所有节点都满足左子树<该节点<右子树,因此我们按照这个顺序查找最小值即可,代码如下。同理,也可以查找最大值。

	//查找最小值
	public int minimum(){
		BinaryTreeNode current = new BinaryTreeNode();
		current = root;
		while(current.left != null){
			current = current.left;
		}
		return current.val;
	}

  查找结点:根据查找二叉树的性质查找即可,代码如下

//查找结点
	public BinaryTreeNode find(int value){
		BinaryTreeNode current = root;
		while(value != current.val){
			if(value < current.val){
				current = current.left;
			}else{
				current = current.right;
			}
			if(current == null)
				return null;//没有找到
		}
		return current;
	}

  删除节点:对于二叉树来说,删除节点最为复杂,删除节点首先要查找结点,按照节点二叉树的特性首先找到要删除的节点,查找的代码如下:

BinaryTreeNode current;
		BinaryTreeNode parent = new BinaryTreeNode();
		boolean isLeftTrue = false;
		current = root;
		//首先查找这个节点
		while(current.val != value){
			parent = current;//保存父类信息
			if(value < current.val){
				current = current.left;
				isLeftTrue = true;
			}else{
				current = current.right;
				isLeftTrue = false;
			}
			if(current == null){
				//判断是否找到
				return false;
			}
		}

  然后根据要删除节点的情况分为四种情况,分别是没有孩子的节点(叶子)、有左孩子的节点、有有孩子的节点和有两个孩子的节点。

对于没有孩子的节点,直接删除即可

//删除一个子节点的情况
		if(current.left == null && current.right == null){
			//节点是叶子节点
			if(current == root)//判断是根节点
				root = null;
			else if(isLeftTrue)//删除左节点
				parent.left = null;
			else//删除右节点
				parent.right = null;
		}

  对于只有一个孩子的节点,先删除该节点,然后将该孩子节点直接放到该节点的位置即可,代码如下:

else if(current.left == null){
			//只有右节点
			if(current == root)//判断是根节点
				root = null;
			else if(isLeftTrue)//删除左节点
				parent.left = current.right;
			else//删除右节点
				parent.right = current.right;
		}else if(current.right == null){
			//只有左节点
			if(current == root)//判断是根节点
				root = null;
			else if(isLeftTrue)//删除左节点
				parent.left = current.left;
			else//删除右节点
				parent.right = current.left;
		}

  对于两个孩子的节点,首先要找到后继节点,然后将后继节点来代替该节点即可,所谓后续节点即也就是中序后继(比这个节点大一点的数),对于某一结点的后继节点一定存在于右子树,因为只有右子树比这个节点大,然后找大的最少的树,寻找右子树的最小值即可(沿着左孩子寻找即可)。寻找后继节点的代码如下:

//查找后继节点
	private BinaryTreeNode getSuccessor(BinaryTreeNode delNode){
		
		BinaryTreeNode current = delNode.right;//先定位到右子树
		BinaryTreeNode parent = delNode;
		//寻找右子树的最小值
		while(current.left!=null){
			parent = current;
			current = current.left;
		}
		//如果继点有分支(一定是右分支),因为这个继点要移动到删除节点的位置,需要将继点的右分支放在继点的位置
		if(current != delNode.right){
			parent.left = current.right;//继点的右分支放在继点的位置
			current.right = delNode.right;//将继点放到删除节点的位置
		}
		return current;
	}

  然后将继点放在删除的节点位置即可,代码如下:

else{
			//有两个分支节点
			BinaryTreeNode successor = getSuccessor(current);
			if(current == root){
				root = successor;
			}else if(isLeftTrue){
				parent.left = successor;
			}else{
				parent.right = successor;
			}
			successor.left = current.left;
		}

  二叉树删除节点的整体代码如下:

//根据值,删除节点
	public boolean delete(int value){
		BinaryTreeNode current;
		BinaryTreeNode parent = new BinaryTreeNode();
		boolean isLeftTrue = false;
		current = root;
		//首先查找这个节点
		while(current.val != value){
			parent = current;//保存父类信息
			if(value < current.val){
				current = current.left;
				isLeftTrue = true;
			}else{
				current = current.right;
				isLeftTrue = false;
			}
			if(current == null){
				//判断是否找到
				return false;
			}
		}
		
		//删除一个子节点的情况
		if(current.left == null && current.right == null){
			//节点是叶子节点
			if(current == root)//判断是根节点
				root = null;
			else if(isLeftTrue)//删除左节点
				parent.left = null;
			else//删除右节点
				parent.right = null;
		}else if(current.left == null){
			//只有右节点
			if(current == root)//判断是根节点
				root = null;
			else if(isLeftTrue)//删除左节点
				parent.left = current.right;
			else//删除右节点
				parent.right = current.right;
		}else if(current.right == null){
			//只有左节点
			if(current == root)//判断是根节点
				root = null;
			else if(isLeftTrue)//删除左节点
				parent.left = current.left;
			else//删除右节点
				parent.right = current.left;
		}else{
			//有两个分支节点
			BinaryTreeNode successor = getSuccessor(current);
			if(current == root){
				root = successor;
			}else if(isLeftTrue){
				parent.left = successor;
			}else{
				parent.right = successor;
			}
			successor.left = current.left;
		}
			
		return true;
	} 
	
	//查找后继节点
	private BinaryTreeNode getSuccessor(BinaryTreeNode delNode){
		
		BinaryTreeNode current = delNode.right;//先定位到右子树
		BinaryTreeNode parent = delNode;
		//寻找右子树的最小值
		while(current.left!=null){
			parent = current;
			current = current.left;
		}
		//如果继点有分支(一定是右分支),因为这个继点要移动到删除节点的位置,需要将继点的右分支放在继点的位置
		if(current != delNode.right){
			parent.left = current.right;//继点的右分支放在继点的位置
			current.right = delNode.right;//将继点放到删除节点的位置
		}
		return current;
	}

  二叉树所有代码及测试程序如下所示:

package dataStructure;

import java.util.LinkedList;
import java.util.Queue;



public class BinaryTree {
	private BinaryTreeNode root;
	private int treeSize; 
	
	class BinaryTreeNode{
		public BinaryTreeNode left, right;//左子数,右子数
		int val;//节点元素
		//提供不同的初始化函数
		public BinaryTreeNode(){
			left = right = null;
		}
		public BinaryTreeNode(int val){
			this.val = val;
			left = right = null;
		}
		public BinaryTreeNode(int val, BinaryTreeNode left, BinaryTreeNode right){
			this.val = val;
			this.left = left;
			this.right = right;
		}
	}
	
	//访问一个节点
	private void visitTreeNode(BinaryTreeNode binaryTreeNode){
		System.out.print(binaryTreeNode.val+" ");
	}
	
	//前序遍历
	public void preOrder(BinaryTreeNode binaryTreeNode){
		//前序遍历二叉树
		if(binaryTreeNode != null){
			visitTreeNode(binaryTreeNode);
			preOrder(binaryTreeNode.left);
			preOrder(binaryTreeNode.right);
		}
	}
	
	//中序遍历
	public void inOrder(BinaryTreeNode binaryTreeNode){
		//中序遍历二叉树
		if(binaryTreeNode != null){
			inOrder(binaryTreeNode.left);
			visitTreeNode(binaryTreeNode);
			inOrder(binaryTreeNode.right);
		}
	}
	
	//后续遍历
	public void postOrder(BinaryTreeNode binaryTreeNode){
		//后续遍历二叉树
		if(binaryTreeNode != null){
			postOrder(binaryTreeNode.left);
			postOrder(binaryTreeNode.right);
			visitTreeNode(binaryTreeNode);
		}
	}
	
	//层次遍历
	public void levelOrder(BinaryTreeNode binaryTreeNode){
		//层次遍历二叉树
		Queue<BinaryTreeNode> nodeQueue = new LinkedList<BinaryTreeNode>();
		BinaryTreeNode last=binaryTreeNode;
		BinaryTreeNode nlast=binaryTreeNode;
		while(binaryTreeNode != null){
			visitTreeNode(binaryTreeNode);
			last = binaryTreeNode;
			//将孩子加入队列
			if(binaryTreeNode.left != null){
				nodeQueue.offer(binaryTreeNode.left);
			}
			if(binaryTreeNode.right != null){
				nodeQueue.offer(binaryTreeNode.right);
			}
			//提取下一个要访问的节点
			if(nodeQueue.isEmpty() == true){
				return;//此处可以退出循环
			}
			binaryTreeNode = nodeQueue.poll();
			if(last == nlast){
				//该层打印结束,需要换行
				System.out.println();
				if(nlast.right != null){
					nlast = nlast.right;
				}
			}
			
		}
	}
	
	//返回节点数目
	public final int size(){
		return treeSize;
	}
	
	//检查是树否为空
	public final boolean  isEmpty()  {
		return treeSize == 0;
	}
	
	//确定二叉树的高度
	public int heightRoot(){
		return height(root);
	}
	
	private int height(BinaryTreeNode binaryTreeNode){
		int hl, hr;//左树高度,右树高度
		if(binaryTreeNode == null){
			return 0;
		}
		hl = height(binaryTreeNode.left);
		hr = height(binaryTreeNode.right);
		if(hl > hr)
			return ++hl;
		else
			return ++hr;
	}
	
	//查找结点
	public BinaryTreeNode find(int value){
		BinaryTreeNode current = root;
		while(value != current.val){
			if(value < current.val){
				current = current.left;
			}else{
				current = current.right;
			}
			if(current == null)
				return null;//没有找到
		}
		return current;
	}
	
	//增加节点
	public void insert(int value){
		BinaryTreeNode node = new BinaryTreeNode(value);
		if(root == null){
			//将增加的节点设置为根节点
			root = node;
		}else{
			BinaryTreeNode current = root;
			BinaryTreeNode parent = root;
//			while(true){ 
//				if(value < parent.val){
//					current = parent.left;
//					if(current == null){
//						parent.left = node;//插入节点
//						return;
//					}else{
//						parent = parent.left;
//					}
//				}else{
//					current = parent.right;
//					if(current == null){
//						parent.right = node;//插入节点
//						return;
//					}else{
//						parent = parent.right;
//					}
//				}
//			}
			while(current != null){
				parent = current;//记录父类信息,防止丢失父类信息
				if(value < current.val){
					current = current.left;
				}else{
					current = current.right;
				}
			}
			if(value < parent.val){
				parent.left = node;
			}else{
				parent.right = node;
			}
		}
		treeSize++;
	}
	
	//查找最小值
	public int minimum(){
		BinaryTreeNode current = new BinaryTreeNode();
		current = root;
		while(current.left != null){
			current = current.left;
		}
		return current.val;
	}
	
	//根据值,删除节点
	public boolean delete(int value){
		BinaryTreeNode current;
		BinaryTreeNode parent = new BinaryTreeNode();
		boolean isLeftTrue = false;
		current = root;
		//首先查找这个节点
		while(current.val != value){
			parent = current;//保存父类信息
			if(value < current.val){
				current = current.left;
				isLeftTrue = true;
			}else{
				current = current.right;
				isLeftTrue = false;
			}
			if(current == null){
				//判断是否找到
				return false;
			}
		}
		
		//删除一个子节点的情况
		if(current.left == null && current.right == null){
			//节点是叶子节点
			if(current == root)//判断是根节点
				root = null;
			else if(isLeftTrue)//删除左节点
				parent.left = null;
			else//删除右节点
				parent.right = null;
		}else if(current.left == null){
			//只有右节点
			if(current == root)//判断是根节点
				root = null;
			else if(isLeftTrue)//删除左节点
				parent.left = current.right;
			else//删除右节点
				parent.right = current.right;
		}else if(current.right == null){
			//只有左节点
			if(current == root)//判断是根节点
				root = null;
			else if(isLeftTrue)//删除左节点
				parent.left = current.left;
			else//删除右节点
				parent.right = current.left;
		}else{
			//有两个分支节点
			BinaryTreeNode successor = getSuccessor(current);
			if(current == root){
				root = successor;
			}else if(isLeftTrue){
				parent.left = successor;
			}else{
				parent.right = successor;
			}
			successor.left = current.left;
		}
			
		return true;
	} 
	
	//查找后继节点
	private BinaryTreeNode getSuccessor(BinaryTreeNode delNode){
		
		BinaryTreeNode current = delNode.right;//先定位到右子树
		BinaryTreeNode parent = delNode;
		//寻找右子树的最小值
		while(current.left!=null){
			parent = current;
			current = current.left;
		}
		//如果继点有分支(一定是右分支),因为这个继点要移动到删除节点的位置,需要将继点的右分支放在继点的位置
		if(current != delNode.right){
			parent.left = current.right;//继点的右分支放在继点的位置
			current.right = delNode.right;//将继点放到删除节点的位置
		}
		return current;
	}
	
	public static void main(String[] args){
		BinaryTree tree = new BinaryTree();
//		二叉树结构如下
//				    10 
//			  6             15 
//		  4      8       12      18 
//		1   5   7  9   11 13    16 19 		
		tree.insert(10);
		tree.insert(6); 
		tree.insert(15);
		tree.insert(4);
		tree.insert(8);
		tree.insert(1);
		tree.insert(5);
		tree.insert(7);
		tree.insert(9);
		tree.insert(12);
		tree.insert(18);
		tree.insert(11);
		tree.insert(13);
		tree.insert(16);
		tree.insert(19);

		System.out.println("
前序遍历");
		tree.preOrder(tree.root);
		System.out.println("
中序遍历");
		tree.inOrder(tree.root);
		System.out.println("
后序遍历");
		tree.postOrder(tree.root);
		System.out.println("
层次遍历");
		tree.levelOrder(tree.root);
		System.out.println("
寻找"+tree.find(10).val);
		tree.delete(8);
		tree.levelOrder(tree.root);
		System.out.println("
");
		tree.delete(11); 
		tree.levelOrder(tree.root);
		System.out.println("
");
		tree.delete(12); 
		tree.levelOrder(tree.root);
		System.out.println("
");
		tree.delete(4);
		tree.levelOrder(tree.root);
	}
}

  运行结果如下:

前序遍历
10 6 4 1 5 8 7 9 15 12 11 13 18 16 19
中序遍历
1 4 5 6 7 8 9 10 11 12 13 15 16 18 19
后序遍历
1 5 4 7 9 8 6 11 13 12 16 19 18 15 10
层次遍历
10
6 15
4 8 12 18
1 5 7 9 11 13 16 19
寻找10
10
6 15
4 9 12 18
1 5 7 11 13 16 19

10
6 15
4 9 12 18
1 5 7 13 16 19

10
6 15
4 9 13 18
1 5 7 16 19

10
6 15
5 9 13 18
1 7 16 19

 此外二叉树还可与用数组实现,采用数组实现不用采用指针记录连接关系,每个节点的左节点是index*2+1,右节点是诗index*2+2,在节点删除的时候,需要手动将节点置空。采用数组实现的二叉树,会存在空间浪费,效率也不是很高,空间表示二叉树的结果如图所示:

完整代码实现如下所示:

package dataStructure;

import java.util.LinkedList;
import java.util.Queue;



public class BinaryTreeInArray {
	private int root; 
	private int treeSize; 
	private int[] nodeArray = new int[30];
	
	public BinaryTreeInArray(){
		root = 0;
		treeSize = 0;
		for(int i=0; i<30; i++)
			nodeArray[i]  = -1;
	}
	//访问一个节点
	private void visitTreeNode(int binaryTreeNode){
		System.out.print(nodeArray[binaryTreeNode]+" ");
	}
	
	//前序遍历
	public void preOrder(int binaryTreeNode){
		//前序遍历二叉树
		if(binaryTreeNode >= 0 && binaryTreeNode < treeSize){
			visitTreeNode(binaryTreeNode);
			preOrder(2*binaryTreeNode+1);
			preOrder(2*binaryTreeNode+2);
		}
	}
	
	//中序遍历
	public void inOrder(int binaryTreeNode){
		//中序遍历二叉树
		if(binaryTreeNode >= 0 && binaryTreeNode < treeSize){
			inOrder(2*binaryTreeNode+1);
			visitTreeNode(binaryTreeNode);
			inOrder(2*binaryTreeNode+2);
		}
	}
	
	//后续遍历
	public void postOrder(int binaryTreeNode){
		//后续遍历二叉树
		if(binaryTreeNode >= 0 && binaryTreeNode < treeSize){
			postOrder(2*binaryTreeNode+1);
			postOrder(2*binaryTreeNode+2);
			visitTreeNode(binaryTreeNode);
		}
	}
	
	//层次遍历
	public void levelOrder(int binaryTreeNode){
		//层次遍历二叉树
		Queue<Integer> nodeQueue = new LinkedList<Integer>();
		int last=binaryTreeNode;
		int nlast=binaryTreeNode;
		while(binaryTreeNode >= 0 && binaryTreeNode < treeSize){
			visitTreeNode(binaryTreeNode);
			last = binaryTreeNode;
			//将孩子加入队列
			if(2*binaryTreeNode+1 >= 0 && 2*binaryTreeNode+1 < treeSize){
				nodeQueue.offer(2*binaryTreeNode+1);
			}
			if(2*binaryTreeNode+2 >= 0 && 2*binaryTreeNode+2 < treeSize){
				nodeQueue.offer(2*binaryTreeNode+2);
			}
			//提取下一个要访问的节点
			if(nodeQueue.isEmpty() == true){
				return;//此处可以退出循环
			}
			binaryTreeNode = nodeQueue.poll();
			if(last == nlast){
				//该层打印结束,需要换行
				System.out.println();
				if(2*nlast+2 >= 0 && 2*nlast+2 < treeSize){
					nlast = 2*nlast+2;
				}
			}
			
		}
	}
	
	//返回节点数目
	public final int size(){
		return treeSize;
	}
	
	//检查是树否为空
	public final boolean  isEmpty()  {
		return treeSize == 0;
	}
	
	//确定二叉树的高度
	public int heightRoot(){
		return height(root);
	}
	
	private int height(int binaryTreeNode){
		int hl, hr;//左树高度,右树高度
		if(binaryTreeNode <= 0 && binaryTreeNode < treeSize){
			return 0;
		}
		hl = height(2*binaryTreeNode+1);
		hr = height(2*binaryTreeNode+2);
		if(hl > hr)
			return ++hl;
		else
			return ++hr;
	}
	
	//查找结点
	public int find(int value){
		int current = root;
		while(value != nodeArray[current]){
			if(value < nodeArray[current]){
				if(2*current+1 < treeSize)
					current = nodeArray[2*current+1];
				else
					return -1;//没有找到
			}else{ 
				if(2*current+2 < treeSize)
					current = nodeArray[2*current+2];
				else
					return -1;//没有找到
			} 
		}
		return nodeArray[current];
	}
	
	//增加节点
	public void insert(int value){ 
		int node = value;
		if(nodeArray[root] == -1){
			//将增加的节点设置为根节点
			nodeArray[root] = node;
		}else{
			int current = root;
			int parent = root;
//			while(true){ 
//				if(value < nodeArray[parent]){
//					current = nodeArray[2*parent+1];
//					if(current >= 0 && current < treeSize){
//						nodeArray[2*parent+1] = node;//插入节点
//						return;
//					}else{
//						nodeArray[parent] = nodeArray[2*parent+1];
//					}
//				}else{
//					current = nodeArray[2*parent+2];
//					if(current >= 0 && current < treeSize){
//						nodeArray[2*parent+2] = node;//插入节点
//						return;
//					}else{
//						parent = nodeArray[2*parent+2];
//					}
//				}
//			}
			while(nodeArray[current] != -1){
				parent = current;//记录父类信息,防止丢失父类信息
				if(value < nodeArray[current]){
					current = 2*current + 1;
				}else{
					current = 2*current + 2;
				}
			}
			nodeArray[current] = node;
		}
		treeSize++;
	}
	
	//查找最小值
	public int minimum(){
		int current = root;
		while(nodeArray[2*current + 1] != -1){
			current = nodeArray[2*current + 1];
		}
		return nodeArray[current];
	}
	
	//根据值,删除叶子
	public boolean delete(int value){
		int current;
		int parent = -1;
		boolean isLeftTrue = false;
		current = root;
		//首先查找这个节点
		while(nodeArray[current] != value){
			parent = current;//保存父类信息
			if(value < nodeArray[current]){
				if(2*current+1 < treeSize){ 
					current = 2*current+1;
					isLeftTrue = true;
				}else
					return false;
			}else{
				if(2*current+2 < treeSize){
					current = 2*current+2;
					isLeftTrue = false;
				}else
					return false; 
			} 
		}
		
		//删除一个子节点的情况
		if(nodeArray[2*current+1] == -1 && nodeArray[2*current+2] == -1){
			//节点是叶子节点
			if(current == root)//判断是根节点
				nodeArray[root] = -1;
			else if(isLeftTrue)//删除左节点
				nodeArray[2*parent+1] = -1;
			else//删除右节点
				nodeArray[2*parent+2] = -1;
		}else if(nodeArray[2*current+1] == -1){
			//只有右节点
			if(current == root)//判断是根节点
				nodeArray[root] = nodeArray[2*current+2];
			else if(isLeftTrue)//删除左节点
				nodeArray[2*parent+1] = nodeArray[2*current+2];
			else//删除右节点
				nodeArray[2*parent+2] = nodeArray[2*current+2];
			nodeArray[2*current+2] = -1;
		}else if(nodeArray[2*current+2] == -1){
			//只有左节点
			if(current == root)//判断是根节点
				nodeArray[root] = nodeArray[2*current+1];
			else if(isLeftTrue)//删除左节点
				nodeArray[2*parent+1] = nodeArray[2*current+1];
			else//删除右节点
				nodeArray[2*parent+2] = nodeArray[2*current+1];
			nodeArray[2*current+1] = -1;
		}else{
			//有两个分支节点
			int successor = getSuccessor(current);
			if(current == root){
				nodeArray[root] = nodeArray[successor];
			}else if(isLeftTrue){
				nodeArray[2*parent+1] = nodeArray[successor];
			}else{
				nodeArray[2*parent+2] = nodeArray[successor];
			} 
			nodeArray[successor] = -1;
		}
			
		return true;
	} 
	
	//查找后继节点
	private int getSuccessor(int delNode){
		
		int current = 2*delNode+2;
		int parent = delNode;
		while(nodeArray[2*current+1] != -1){
			parent = current;
			current = 2*current+1;
		}
		//此处是删除子节点有分支的方法
//		if(current != 2*delNode+2){
//			nodeArray[2*parent+1] = nodeArray[2*current+2];//将继点的右节点连接到父类的左节点,空出继点
////			nodeArray[2*parent+2] = -1;//右
//		}
		return current;
	}
	
	public static void main(String[] args){
		BinaryTreeInArray tree = new BinaryTreeInArray();
//		二叉树结构如下
//				    10 
//			  6             15 
//		  4      8       12      18 
//		1   5   7  9   11 13    16 19 		
		tree.insert(10);
		tree.insert(6); 
		tree.insert(15);
		tree.insert(4);
		tree.insert(8);
		tree.insert(1);
		tree.insert(5);
		tree.insert(7);
		tree.insert(9);
		tree.insert(12);
		tree.insert(18);
		tree.insert(11);
		tree.insert(13);
		tree.insert(16);
		tree.insert(19);

		System.out.println("
前序遍历");
		tree.preOrder(tree.root);
		System.out.println("
中序遍历");
		tree.inOrder(tree.root);
		System.out.println("
后序遍历");
		tree.postOrder(tree.root);
		System.out.println("
层次遍历");
		tree.levelOrder(tree.root);
		System.out.println("
寻找"+tree.find(10));
		tree.delete(8);
		tree.levelOrder(tree.root);
		System.out.println("
");
		tree.delete(11); 
		tree.levelOrder(tree.root);
		System.out.println("
");
		tree.delete(12); 
		tree.levelOrder(tree.root);
		System.out.println("
");
		tree.delete(4);
		tree.levelOrder(tree.root);
	}
}

运行结果如下:


前序遍历
10 6 4 1 5 8 7 9 15 12 11 13 18 16 19
中序遍历
1 4 5 6 7 8 9 10 11 12 13 15 16 18 19
后序遍历
1 5 4 7 9 8 6 11 13 12 16 19 18 15 10
层次遍历
10
6 15
4 8 12 18
1 5 7 9 11 13 16 19
寻找10
10
6 15
4 9 12 18
1 5 7 -1 11 13 16 19

10
6 15
4 9 12 18
1 5 7 -1 -1 13 16 19

10
6 15
4 9 13 18
1 5 7 -1 -1 -1 16 19

10
6 15
5 9 13 18
1 -1 7 -1 -1 -1 16 19

原文地址:https://www.cnblogs.com/feichangnice/p/7727928.html