二分搜索树中的递归

递归思想

递归可以看成“递” 和“归”的过程,重点讨论“递”到低,需要“归”的这一特殊结点的情况,大致可以把整个递归函数分为一下几部分:

递归函数{

“递”停止条件


“归”的过程(返回计算好的值)

}

重点在于:
1)找出“递”的终止条件
2)找出“归”的规律
整个计算过程可以看作重复有限次相同的动作得出的结果

从1到100累加

public class Main {

	public static int Sum(int x) {
	//x==1即为“递”的终止条件,函数可以回头开始“归"
		if(x==1) 
			return 1;
		
		//return 的过程即是往回”归“的过程
		//”归“的同时是重复每一个基本的运算单位,即:当前数加上当前数后的求和
		return x+Sum(x-1);
	}
	
	public static void main(String[] args) {
	
		System.out.println(Sum(100));
		
	}
}

从该题中可看出,递归即是重复地将大的问题缩小,即缩到最小的情况就是x==1。
我们就求出了sum(1)的值,根据sum(x)=x+sum(x-1),往回”归“,就可得到最终结果

由此可以得出,递归的核心思想在于”递“与”归“
我们在解决问题时需要注意:

  1. “递"的”边界”
  2. "归"的算法

整体来说,在编写”归“这一部分代码时,需要从整体来看,将Sum函数直接看成x后的数字的累加和,避免思路混乱

add 方法

由于二叉树中增加数据只会增加到叶子结点后,据此,我们可以写出基本思路:

  • 根据输入数据的大小,与结点的左右子结点进行大小比较,判断该数据应存放的位置
  • 遇到node==null的位置,说明该位置就是该数据存放的位置

其中,我们可以发现,将node顺着树中的分支向下移动的过程是重复的,重复终止条件就是node==null的情况,即可以用递归编写这个过程

  • 递:node顺着树中的分支向下移动

  • 归:node==null,并对该node赋值

由于递的过程中,该节点的左右子树可能改变,故需对它们的左右子树重新赋值

    public void add(E e) {
        	root=add(root,e);
        	
        }
        
        private Node add(Node node,E e) {
        	if(node==null) {
        		size++;
        		node=new Node(e);
        		return node;
        	}
        	
        	if(node.e.compareTo(e)<0)
        		node.right=add(node.right,e);
        	if(node.e.compareTo(e)>0)
        		node.left=add(node.left,e);
        	
        	return node;//由于当前结点有可能改变,故要return node
        }

其中,用到了public方法和private方法来解决,private用来具体解决递归过程

contains方法

  • 同样的分别创建public和private的contains方法,private用来递归
  • “递”的停止条件为node为空的情况
  • “递”的过程中需根据传入参数判断向下判断的位置
  • 若二者相等,返回true,若到底还不相等,返回false
 public boolean contains(E e) {
        	
        	return contains(root,e);
        }
        
        private boolean contains(Node node,E e) {
        	if(node==null) {
        		return false;
        	}
        	
        	if(node.e.compareTo(e)<0)
        		return contains(node.left,e);
        	else if(node.e.compareTo(e)>0)
        		return contains(node.right,e);
        	else
        	return true;
        	
        }

minimum方法

想要寻找二分搜索树中的最小值,只需找到最底层的左节点即可

  • 即递归终止条件就是node.next==null
  • “递”的过程就是在结点的左子树中寻找最小结点,并返回该节点
public E minimum() {
		return minimum(root).e; 
	}
	private Node minimum(Node node) {
		if(node.left==null) {
			return node;
		}
		
		return minimum(node.left);
		
	}

maximum的方法同理

public E maximum() {
        	if(size==0)
        		throw new IllegalArgumentException("BST is empty.");
        	
        	return maximum(root).e;
        	
        }
        
        private Node maximum(Node node) {
        	if(node.right==null)
        		return node;
        	
        	return maximum(node.right);
        	
        }

removeMin方法

移除二分搜索树中的最小树,只需移除minimum就行

  • 先记录minimum为 ret ,再返回
  • 递归中,与minimum相似,判断node.next==null即为移除对象,将node.right与上一结点连接
  • node的左子树就是remove(node.left)
public E removeMin() {
        	E ret=minimum();
        	root=removeMin(root);
        	return ret;
        }
        
        private Node removeMin(Node node) {
        	
        	if(node.left==null) {
        		Node rightNode=node.right;
        		node.right=null;
        		size--;
        		return rightNode;
        	}

removeMax同理

public E removeMax() {
        	
        E ret=maximum();
        root=removeMax(root);
        	return ret;
        }
        
        private Node removeMax(Node node) {
        	
        	if(node.right==null) {
        		Node leftNode=node.left;
        		node.left=null;
        		return leftNode;
        	}
        	
        	node.right=removeMax(node.right);
        	return node;
        	
        }

remove方法

remove方法稍微复杂一些,先要寻找需要移除的数据,再根据数据的位置移除

  • 先判断递归的停止条件:node==null
  • 再根据删除数据与结点大小,决定在左右哪个子树中寻找
  • 删除也分为三种情况
    1)node.leftnull,将node.right与上一结点连接
    2)node.right
    null,将node.left与上一结点连接
    3)将该结点的node.right中的minimum代替删除节点,并将该节点连接removeMin(node.right)的结果
//与add,minimum等方法不同,remove大致可分为,查和删两步,不是单纯的递归
        public void remove(E e) {
        	
        	root=remove(root,e);
        }
        
        private Node remove(Node node,E e) {
        	//递归终止条件
        	if(node==null) {
        		return null;
        	}
        	
        	//当e不等于node中的e时,均需要继续"递"
        	if(e.compareTo(node.e)<0) {
        		node.left=remove(node.left,e);//node.left可能改变,故要用node.left
        		return node;
        	}
        	else if(e.compareTo(node.e)>0) {
        		node.right=remove(node.right,e);//node.left可能改变,故要用node.left
        		return node;
        	}
        	
        	else {//要移除的情况分为三种
        		if(node.left==null) {
        			Node rightNode=node.right;
                    node.right=null;
                    size--;
        			return rightNode;
        		}
        		
        		if(node.right==null) {
        			Node leftNode=node.left;
        			node.right=null;
        			size--;
        			return leftNode;
        		}
        		else {
        		Node successor=minimum(node.right);
        		successor.right=removeMin(node.right);
        		successor.left=node.left;
        		
        		
        		node.left=node.right=null;
        		return successor;
        		}
        		
        	}
        	
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值