树的实现Java

树采用左孩子-右兄弟链接结构。

由于树与二叉树之间有自然对应的关系,故可以把树转换为对应的二叉树。

每个结点都有三部分:大孩子结点firstChild、数据域data、大兄弟结点nextBrother。

/**
 * 树结点类
 * @author liangxiamoyi
 *
 */
public class TreeNode {
	/**
	 * 数据值
	 */
	protected char data;
	/**
	 * 大孩子结点
	 */
	protected TreeNode firstChild;
	/**
	 * 大兄弟结点
	 */
	protected TreeNode nextBrother;
	/**
	 * 构造方法
	 * @param data 数据值
	 * @param first 大孩子结点
	 * @param next 大兄弟结点
	 */
	public TreeNode(char data,TreeNode first,TreeNode next){
		this.data=data;
		this.firstChild=first;
		this.nextBrother=next;
	}
}
import java.util.Scanner;

/**
 * 树
 * @author liangxiamoyi
 *
 */
public class Tree {
	/**
	 * 根节点
	 */
	private TreeNode root;
	/**
	 * 输入终止符
	 */
	private char stop;
	/**
	 * 构造方法
	 */
	public Tree(){
		this.root=null;
	}
	/**
	 * 在以t为根节点的树中,搜索p所指结点的父节点
	 * @param t 根节点
	 * @param p 
	 * @return p的父节点
	 */
	public TreeNode findFather(TreeNode t,TreeNode p){
		if(t==null||p==null)return null;
		TreeNode result=null;
		TreeNode q=t.firstChild;
		while(q!=null&&q!=p){
			result=findFather(q,p);
			if(result==null)q=q.nextBrother;
			else return result;
		}
		if(q==p)return t;
		else return null;
	}
	/**
	 * 在根节点为t的树中,搜索数据域为item的结点
	 * @param t 根节点
	 * @param item 数据域
	 * @return 数据域为item的结点
	 */
	public TreeNode find(TreeNode t,char item){
		if(t==null)return null;
		TreeNode result=null;
		if(t.data==item)return t;
		else{
			TreeNode p=t.firstChild;
			while(p!=null&&(result=find(p,item))==null){
				p=p.nextBrother;
			}
			return result;
		}
	}
	/**
	 * 在以t为根节点的树中删除以p为根的子树
	 * @param t 根节点
	 * @param p 子树的根
	 */
	public void delSubTree(TreeNode t,TreeNode p){
		if(t!=null&& p!=null){
			TreeNode q=null;
			TreeNode result=null;
			result=findFather(t, p);
			if(result!=null){
				if(result.firstChild==p){
					result.firstChild=p.nextBrother;
					return;
				}
				else{
					q=result.firstChild;
					while(q.nextBrother!=p)q=q.nextBrother;
					q.nextBrother=p.nextBrother;
					return ;
				}
			}
			else{
				root=null;
			}
		}
	}
	/**
	 * 先根遍历
	 * @param t 根节点
	 */
	public void preOrder(TreeNode t){
		if(t!=null){
			System.out.print(t.data+" ");
			TreeNode child=null;
			child=t.firstChild;
			while(child!=null){
				preOrder(child);
				child=child.nextBrother;
			}
		}
	}
	/**
	 * 非递归先根遍历
	 * @param t 根节点
	 */
	public void norecPreOrder(TreeNode t){
		if(t==null)return;
		AStack<TreeNode> s=new AStack<>(20);
		TreeNode p=t;
		do{
			while(p!=null){
				System.out.print(p.data+" ");
				s.push(p);
				p=p.firstChild;
			}
			while(p==null&&!s.isEmpty()){
				p=s.pop();
				p=p.nextBrother;
			}
		}while(!s.isEmpty());
	}
	/**
	 * 层次遍历
	 * @param t 根节点
	 */
	public void levelOrder(TreeNode t){
		AQueue<TreeNode> a=new AQueue<TreeNode>(20);
		if(t!=null){
			TreeNode p;
			a.insert(t);
			while(!a.isEmpty()){
				p=a.delete();
				System.out.print(p.data+" ");
				p=p.firstChild;
				while(p!=null){
					a.insert(p);
					p=p.nextBrother;
				}
			}
		}
	}
	public void createTree(char stop){
		this.stop=stop;
		this.root=create();
	}
	/**
	 * <p>创建一棵树</p>
	 * <p>将firstChild记为左孩子,将nextBrother记做右孩子</p>
	 * <p>输入时按二叉树先根遍历的顺序输入</p>
	 * @return 根节点
	 */
	public TreeNode create(){
		TreeNode t,l,r;
		char item;
		Scanner sc=new Scanner(System.in);
		item=sc.next().charAt(0);
		if(item==stop){
			t=null;
			return t;
		}
		else{
			t=new TreeNode(item, null, null);
			l=create();
			t.firstChild=l;
			r=create();
			t.nextBrother=r;
			return t;
		}
	}
	//测试
	public static void main(String[] args){
//		测试数据
//		a
//		b
//		z
//		c
//		e
//		z
//		f
//		z
//		z
//		d
//		z
//		z
//		z
		Tree tree=new Tree();
		tree.createTree('z');
		System.out.println("先根遍历:");
		tree.preOrder(tree.root);
		System.out.println();
		System.out.println("非递归先根遍历:");
		tree.norecPreOrder(tree.root);
		System.out.println();
		System.out.println("层次遍历:");
		tree.levelOrder(tree.root);
		System.out.println();
		System.out.println("请输入你想查询的结点的数据:");
		Scanner sc=new Scanner(System.in);
		char item=sc.next().charAt(0);
		System.out.println("父结点:");
		System.out.println(tree.findFather(tree.root, tree.find(tree.root, item)).data);
	}
}
测试结果:




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值