数据结构之二叉树

 



 

    二叉树存储结构结点定义:

public class BinaryTreeNode implements Node {
	private Object data; //数据域
	private BinaryTreeNode parent; //父结点
	private BinaryTreeNode lChild; //左孩子
	private BinaryTreeNode rChild; //右孩子
	private int height; //以该结点为根的子树的高度
	private int size; //该结点子孙数(包括结点本身)

	public BinaryTreeNode() { this(null); }
	public BinaryTreeNode(Object e) {
		data = e; height = 0; size = 1;
		parent = lChild = rChild = null;
	}
	
	/******Node 接口方法******/
	public Object getData() { return data; }
	public void setData(Object obj) { data = obj;}
	/******辅助方法,判断当前结点位置情况******/
	//判断是否有父亲
	public boolean hasParent() { return parent != null;}
	//判断是否有左孩子
	public boolean hasLChild() { return lChild ! =null;}
	//判断是否有右孩子
	public boolean hasRChild() { return rChild != null;}
	//判断是否为叶子结点
	public boolean isLeaf() { return !hasLChild() && !hasRChild();}
	//判断是否为某结点的左孩子
	public boolean isLChild() { return (hasParent() && this == parent.lChild);}
	//判断是否为某结点的右孩子
	public boolean isRChild() { return (hasParent() && this == parent.rChild);}
	/******与height 相关的方法******/
	//取结点的高度,即以该结点为根的树的高度
	public int getHeight() { return height; }
	//更新当前结点及其祖先的高度
	public void updateHeight() {
		int newH = 0;//新高度初始化为0,高度等于左右子树高度加1 中的大者
		if (hasLChild()) newH = Math.max(newH, 1 + getLChild().getHeight());
		if (hasRChild()) newH = Math.max(newH, 1 + getRChild().getHeight());
		if (newH == height) return; //高度没有发生变化则直接返回
		height = newH; //否则更新高度
		if (hasParent()) getParent().updateHeight(); //递归更新祖先的高度
	}
	/******与size 相关的方法******/
	//取以该结点为根的树的结点数
	public int getSize() { return size; }
	//更新当前结点及其祖先的子孙数
	public void updateSize() {
		size = 1; //初始化为1,结点本身
		if (hasLChild()) size += getLChild().getSize(); //加上左子树规模
		if (hasRChild()) size += getRChild().getSize(); //加上右子树规模
		if (hasParent()) getParent().updateSize(); //递归更新祖先的规模
	}
	/******与parent 相关的方法******/
	//取父结点
	public BinaryTreeNode getParent() { return parent; }
	//断开与父亲的关系
	public void sever() {
		if (!hasParent()) return;
		if (isLChild()) parent.lChild = null;
		else parent.rChild = null;
		parent.updateHeight(); //更新父结点及其祖先高度
		parent.updateSize(); //更新父结点及其祖先规模
		parent = null;
	}
	/******与lChild 相关的方法******/
	//取左孩子
	public BinaryTreeNode getLChild() { return lChild; }
	//设置当前结点的左孩子,返回原左孩子
	public BinaryTreeNode setLChild(BinaryTreeNode lc) {
		BinaryTreeNode oldLC = this.lChild;
		if (hasLChild()) { lChild.sever();} //断开当前左孩子与结点的关系
		if (lc != null){
			lc.sever(); //断开lc 与其父结点的关系
			this.lChild = lc; //确定父子关系
			lc.parent = this;
			this.updateHeight(); //更新当前结点及其祖先高度
			this.updateSize(); //更新当前结点及其祖先规模
		}
		return oldLC; //返回原左孩子
	}
	/******与rChild 相关的方法******/
	//取右孩子
	public BinaryTreeNode getRChild() { return rChild; }
	//设置当前结点的右孩子,返回原右孩子
	public BinaryTreeNode setRChild(BinaryTreeNode rc) {
		BinaryTreeNode oldRC = this.rChild;
		if (hasRChild()) { rChild.sever();} //断开当前右孩子与结点的关系
		if (rc != null){
			rc.sever(); //断开lc 与其父结点的关系
			this.rChild = rc; //确定父子关系
			rc.parent = this;
			this.updateHeight(); //更新当前结点及其祖先高度
			this.updateSize(); //更新当前结点及其祖先规模
		}
		return oldRC; //返回原右孩子
	}
}

 


 

    二叉树遍历:

public class BinaryTree { 
	private BinaryTreeNode root;
	private Strategy strategy;
	
	public BinaryTree() { this(null, null); }
	public BinaryTree(BinaryTreeNode root, Strategy strategy) {
		this.root = root;
		this.strategy = strategy;
	}
	
	//先序遍历二叉树
	public Iterator preOrder() {
		LinkedList list = new LinkedListDLNode();
		preOrderRecursion(this.root, list);
		//preOrderTraverse (root,list);
		return list.elements();
	}
	//先序遍历的递归算法
	private void preOrderRecursion(BinaryTreeNode rt, LinkedList list) {
		if (rt == null) return; //递归基,空树直接返回
		list.insertLast(rt); //访问根结点
		preOrderRecursion(rt.getLChild(), list); //遍历左子树
		preOrderRecursion(rt.getRChild(), list); //遍历右子树
	}
	//先序遍历的非递归算法
	private void preOrderTraverse(BinaryTreeNode rt, LinkedList list) {
		if (rt == null) return;
		BinaryTreeNode p = rt;
		Stack s = new StackLinked();
		while (p != null) {
			while (p != null) { //向左走到尽头
				list.insertLast(p);	//当前遍历节点
				if (p.hasRChild())
					s.push(p.getRChild()); //右子树根结点入栈
				p = p.getLChild();
			}
			if (!s.isEmpty()) p = (BinaryTreeNode) s.pop(); //右子树根退栈遍历右子树
		}
	}
	//中序遍历二叉树
	public Iterator inOrder() {
		LinkedList list = new LinkedListDLNode();
		inOrderTraverse(this.root, list);
		return list.elements();
	}
	//中序遍历的非递归算法
	private void inOrderTraverse(BinaryTreeNode rt, LinkedList list) {
		if (rt == null) return;
		BinaryTreeNode p = rt;
		Stack s = new StackLinked();
		while (p != null || !s.isEmpty()) {
			while (p != null) { //一直向左走
				s.push(p); //将根结点入栈
				p = p.getLChild();
			}
			if (!s.isEmpty()) {
				p = (BinaryTreeNode) s.pop();//取出栈顶根结点访问之
				list.insertLast(p);
				p = p.getRChild(); //转向根的右子树进行遍历
			}//if
		}//out while
	}
	//后序遍历二叉树
	public Iterator postOrder() {
		LinkedList list = new LinkedListDLNode();
		postOrderTraverse (this.root,list);
		return list.elements();
	}
	//后序遍历的非递归算法
	private void postOrderTraverse(BinaryTreeNode rt, LinkedList list) {
		if (rt == null) return;
		BinaryTreeNode p = rt;
		Stack s = new StackLinked();
		while(p != null || !s.isEmpty()) {
			while (p != null){ //先左后右不断深入
				s.push(p); //将根节点入栈
				if (p.hasLChild()) 
					p = p.getLChild();
				else 
					p = p.getRChild();
			}
			if (!s.isEmpty()) {
				p = (BinaryTreeNode) s.pop(); //取出栈顶根结点访问之
				list.insertLast(p);
			}
			//满足条件时,说明栈顶根节点右子树已访问,应出栈访问之
			while (!s.isEmpty() && ((BinaryTreeNode) s.peek()).getRChild() == p) {
				p = (BinaryTreeNode)s.pop();
				list.insertLast(p);
			}
			//转向栈顶根结点的右子树继续后序遍历
			if (!s.isEmpty()) 
				p = ((BinaryTreeNode) s.peek()).getRChild();
			else 
				p = null;
		}
	}
	//按层遍历二叉树
	public Iterator levelOrder() {
		LinkedList list = new LinkedListDLNode();
		levelOrderTraverse(this.root, list);
		return list.elements();
	}
	//使用队列完成二叉树的按层遍历
	private void levelOrderTraverse(BinaryTreeNode rt, LinkedList list) {
		if (rt == null) return;
		Queue q = new QueueArray();
		q.enqueue(rt); //根结点入队
		while (!q.isEmpty()) {
			BinaryTreeNode p = (BinaryTreeNode) q.dequeue(); //取出队首结点p 并访问
			list.insertLast(p);
			if (p.hasLChild()) 
				q.enqueue(p.getLChild());//将p 的非空左右孩子依次入队
			if (p.hasRChild()) 
				q.enqueue(p.getRChild());
		}
	}
	//在树中查找元素e,返回其所在结点
	public BinaryTreeNode find(Object e) {
		return searchElement(this.root, e);
	}
	//递归查找元素e
	private BinaryTreeNode searchElement(BinaryTreeNode rt, Object e) {
		if (rt == null) 
			return null;
		if (strategy.equal(rt.getData(), e)) 
			return rt; //如果是根结点,返回根
		BinaryTreeNode result = searchElement(rt.getLChild(), e); //否则在左子树中找
		if (result == null)
			result = searchElement(rt.getRChild(), e); //没找到,在右子树中找
		return result;
	}
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值