二叉树的定义:二叉树是每个结点最多有两个子树的树结构,通常子树被称作“左子树”和“右子树”。二叉树的每个结点最多只有两棵子树,二叉树的子树有左右之分,次序不能颠倒。
下图为一颗二叉树:
二叉搜索树的定义:它是具有下列性质的二叉树,若它的左子树不为空,则左子树上所有结点的值均小于它的根结点的值;若它的右子树不为空,则右子树上所有结点的值均大于它的根结点的值;它的左右子树也分别为二叉搜索树。
下图为一棵二叉搜索树:
下面给出二叉搜索树的建立,删除,遍历(包括前序、中序、后序的递归以及非递归遍历):
import java.util.Stack;
/**
* 二叉树
* @author zxy
*
*/
public class TreeNode {
private int val; //结点数据
private TreeNode left; //左子树
private TreeNode right; //右子树
public TreeNode(int val) {
super();
this.val = val;
}
/**
* 创建二叉搜索树
* @param vals
* @return
*/
public static TreeNode createTree(int[] vals){
if(vals==null || vals.length==0){
return null;
}
TreeNode root=new TreeNode(vals[0]);
for(int i=1;i<vals.length;i++){
insertTree(root, vals[i]);
}
return root;
}
/**
* 向二叉搜索树中插入一个结点
* @param root
* @param val
*/
public static void insertTree(TreeNode root, int val){
if(root==null){
return;
}else{
TreeNode node=root;
while(node!=null){
//指向当前结点的上一结点
TreeNode p=node;
if(val<node.val){
node=node.left;
if(node==null){
p.left=new TreeNode(val);
}
}else{
node=node.right;
if(node==null){
p.right=new TreeNode(val);
}
}
}
}
}
/**
* 二叉树中删除一个结点
* @param root
* @param val
*/
public static void deleteTree(TreeNode root, int val){
if(root==null){
return;
}
TreeNode node=root;
while(node!=null){
//指向当前结点的上一结点
TreeNode p=node;
//删除结点的值小于当前结点的值
if(val<node.val){
node=node.left;
if(node!=null){
//当前结点的值等于删除结点的值
if(node.val==val){
//当前结点没有左子树
if(node.left==null){
//当前结点也没有右子树
if(node.right==null){
//上一结点直接赋null
p.left=null;
//当前结点有右子树
}else{
//将当前结点的右子树赋给上一结点的左子树
p.left=node.right;
}
//当前结点有左子树
}else{
//定义两个结点
//e_front指向当前结点,e指向当前结点的下一结点
TreeNode e_front=node;
TreeNode e=node.left;
//找到最右端的子树,e_front始终指向e的上一结点
while(e.right!=null){
e_front=e;
e=e.right;
}
//如果e_font等于当前结点,表示指针没有移动,当前结点的下一结点没有右子树
if(e_front==node){
e.right=e_front.right;
p.left=e;
}else{
//指针有移动
e_front.right=e.left;
e.left=node.left;
e.right=node.right;
p.left=e;
}
}
}
}
//删除结点的值大于等于当前结点的值(以下同理)
}else {
node=node.right;
if(node!=null){
if(node.val==val){
if(node.left==null){
if(node.right==null){
p.right=null;
}else{
p.right=node.right;
}
}else{
TreeNode e_front=node;
TreeNode e=node.left;
while(e.right!=null){
e_front=e;
e=e.right;
}
if(e_front==node){
e.right=e_front.right;
p.right=e;
}else{
e_front.right=e.left;
e.left=node.left;
e.right=node.right;
p.right=e;
}
}
}
}
}
}
}
/**
* 递归前序遍历
* @param root
*/
public static void pre_out_r(TreeNode root){
if(root!=null){
System.out.print(root.val+" ");
pre_out_r(root.left);
pre_out_r(root.right);
}
}
/**
* 非递归前序遍历
* @param root
*/
public static void pre_out(TreeNode root){
if(root==null){
return;
}
Stack<TreeNode> stack=new Stack<>();
while(true){
while(root!=null){
//打印当前结点,当前结点入栈,进入其左子树
System.out.print(root.val+" ");
stack.push(root);
root=root.left;
}
if(stack.isEmpty()){
break;
}
//退栈,进入其右子树
root=stack.pop();
root=root.right;
}
}
/**
* 递归中序遍历
* @param root
*/
public static void in_out_r(TreeNode root){
if(root!=null){
in_out_r(root.left);
System.out.print(root.val+" ");
in_out_r(root.right);
}
}
/**
* 非递归中序遍历
* @param root
*/
public static void in_out(TreeNode root){
if(root==null){
return;
}
Stack<TreeNode> stack=new Stack<>();
while(true){
//将当前结点和其左子树全部入栈
while(root!=null){
stack.push(root);
root=root.left;
}
if(stack.isEmpty()){
break;
}
//退栈,打印当前结点,进入其右子树
root=stack.pop();
System.out.print(root.val+" ");
root=root.right;
}
}
/**
* 递归后序遍历
* @param root
*/
public static void post_out_r(TreeNode root){
if(root!=null){
post_out_r(root.left);
post_out_r(root.right);
System.out.print(root.val+" ");
}
}
/**
* 非递归后序遍历
* 入栈顺序,当前结点入栈->右子树入栈->左子树入栈
* 出栈顺序,左子树->右子树->当前结点,即为后序遍历
* @param root
*/
public static void post_out(TreeNode root){
if(root==null){
return;
}
//辅助栈
Stack<TreeNode> stack = new Stack<>();
//输出栈
Stack<TreeNode> output = new Stack<>();
TreeNode p = root;
while(p!=null||!stack.isEmpty()){
//当前结点不为空,辅助栈输出栈都入栈,进入其右子树
if(p!=null){
stack.push(p);
output.push(p); //进入待操作栈
p=p.right; //先进入右子树
//当前结点为空,辅助栈退栈,进入其左子树
}else{
p = stack.pop();
p = p.left;
}
}
//输出栈出栈,即为后序遍历顺序
while(!output.isEmpty()){
TreeNode node = output.pop();
System.out.print(node.val+" ");
}
}
public static void main(String[] args) {
int[] vals=new int[]{10,6,20,3,8,15,30,1,7,9,25,40};
TreeNode root=createTree(vals);
post_out(root);
System.out.println();
deleteTree(root, 20);
post_out(root);
}
}