数据结构之关于树的操作(JAVA实现)(三)

28 篇文章 2 订阅

    树的基本结构

     

     public class TreeNode<T>
	{
		public TreeNode<T> leftNode;
		public TreeNode<T> rightNode;
		public T data;

		public TreeNode(T data)
			{
				this.data = data;
			}
	}
    1.构建一颗树(本文以表达式树为例,用后缀表达式构建,我在前一篇已近介绍了如何将中序转换为后续表达式)

        原理:利用栈。步骤:a.当前字符为字符或者数字,则直接构建一个节点,然后入栈

                                            b.当前字符为操作符,则在栈中取出两个节点,将这两个节点作为孩子节点构建一棵树入栈

                                            c.最后将栈中剩下的唯一节点返回,就是要构建的树       

              // 构建一颗字符树,即数学表达式
		public static TreeNode<Character> getTree(String obj)
			{
				// TreeNode<Character> node2=new TreeNode<Character>(null);
				Stack<TreeNode<Character>> stack = new Stack<TreeNode<Character>>();
				for (int i = 0; i < obj.length(); i++)
					{
						char temp = obj.charAt(i);
						if (Character.isLetterOrDigit(temp))// 如果是字母或者数字,那么直接构建一个树,入栈
							{
								TreeNode<Character> node = new TreeNode<Character>(
										temp);
								stack.push(node);
							} else
							// 操作符的话,从栈中取出两个树节点,然后合并成一个节点,操作符为根节点
							{
								TreeNode<Character> node = new TreeNode<Character>(
										temp);
								// 有操作符,栈至少有两个元素
								node.rightNode = stack.pop();
								node.leftNode = stack.pop();
								stack.push(node);
							}
					}
				return stack.pop();
			}
     2.用先序,中序,后序 打印一颗树,这个没有什么好说的

		/*
		 * 递归 打印一棵树 先序,中序,后序
		 */
		// 先序遍历一棵树,(根左右)
		public String printTreePreOreder(TreeNode<T> node)
			{
				String obj = "";
				if (node != null)
					{
						obj += node.data;
						obj += printTreePreOreder(node.leftNode);
						obj += printTreePreOreder(node.rightNode);
					}
				return obj;
			}

		// 中序遍历一棵树(左根右)
		public String printTreeInfixOreder(TreeNode<T> node)
			{
				String obj = "";
				if (node != null)
					{
						if (node.leftNode != null)
							obj += "(";
						obj += printTreeInfixOreder(node.leftNode);
						obj += node.data;
						obj += printTreeInfixOreder(node.rightNode);
						if (node.rightNode != null)
							obj += ")";
					}
				return obj;
			}

		// 后续遍历一棵树(左右根)
		public String printTreePostOreder(TreeNode<T> node)
			{
				String obj = "";
				if (node != null)
					{
						obj += printTreePostOreder(node.leftNode);
						obj += printTreePostOreder(node.rightNode);
						obj += node.data;
					}
				return obj;
			}
  3.得到树的高度(使用递归)

    原理:树根的高度=最大的孩子的高度+1

		// 得到一棵树额高度
		public int getHeight()
			{
				if(this==null)
					return 0;
				if (this.leftNode == null && this.rightNode == null)
					return 1;
				int lHeight = this.leftNode.getHeight();
				int rHeight = this.rightNode.getHeight();
				return lHeight > rHeight ? lHeight + 1 : rHeight + 1;
			}
  4.打印树的第k层(递归实现)

   原理:可以理解为打印根的第k层,即打印根的孩子的第k-1层,当k=0时,可以直接打印出来

   

		// 打印一棵树的第level层
		public void printTreeAtLevel(TreeNode<T> node, int level)
			{
				if (node == null || level < 0)
					return;
				if (level == 0)// 到达目标层
					System.out.print(node.data);
				printTreeAtLevel(node.leftNode, level - 1);
				print(1);///打印一个空格
				printTreeAtLevel(node.rightNode, level - 1);
			}

   5.按层次打印一棵树

   我实现了两种方法:

      方法一:

          知道了树的高度,依次打印出各层的高度。但是这种方法,会在打印任何一层的时候都会从根节点开始,浪费时间

          

		// 按照树的格式打印一棵树,必须按层次打印
		public void printTree()
			{
				int height = getHeight();
				for (int i = 0; i < height; i++)
					{
						print(height * 2 - i);
						printTreeAtLevel(this, i);
						System.out.println();
					}
			}
      方法二:

           用两个队列实现,队列1保存所有的同一层叶节点,队列2保存保存队列1的正在访问的孩子节点 ,队列1访问完以后,将队列2加到队列1(此时是空队列)中,再讲队列2清空

                   

public void printTreeByQueue(TreeNode<T> root)
			{
				Queue<TreeNode<T>> queue1, queue2;
				queue1 = new LinkedList<TreeNode<T>>();
				queue2 = new LinkedList<TreeNode<T>>();
				queue1.add(root);
				queue2.add(root);
				while (!queue2.isEmpty())
					{
						queue2.clear();
						while (!queue1.isEmpty())
							{
								TreeNode<T> node = queue1.poll();
								print(2);
								System.out.print(node.data);
								if (node.leftNode != null)
									queue2.add(node.leftNode);
								if (node.rightNode != null)
									queue2.add(node.rightNode);
							}
						queue1.addAll(queue2);
						System.out.println();
					}

			}



  

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值