数据结构之二叉树创建与遍历

package com.zhiru;

import java.util.Stack;

public class BinaryTree1 {

	private Stack<TreeNode> s;
	private TreeNode root;// 根节点

	public BinaryTree1() {
		root = null;
	}

	public BinaryTree1(char[] x, char[] y) {
		root = createBinTree(x, y, x.length);
	}

	public BinaryTree1(char ref) {
		root = null;
	}

	public TreeNode getRoot() {
		return root;
	}

	/*
	 * 结点类 成员变量:结点中数据data,左孩子lChild,右孩子结点rChild.
	 */
	class TreeNode {
		private char data;
		private TreeNode lChild;
		private TreeNode rChild;

		public TreeNode(char d) {
			data = d;
			lChild = null;
			rChild = null;
		}

		public TreeNode(char d, TreeNode l, TreeNode r) {
			data = d;
			lChild = l;
			rChild = r;
		}
	}

	/*
	 * 计算以r为根的树的结点个数.
	 */
	public int size(TreeNode r) {
		if (r == null)
			return 0;
		else
			return 1 + size(r.lChild) + size(r.rChild);
	}

	/*
	 * 计算以r为根的二叉树的深度.
	 */
	public int height(TreeNode r) {
		if (r == null)
			return 0;
		else {
			int ls = height(r.lChild);
			int rs = height(r.rChild);
			return ls < rs ? rs + 1 : ls + 1;
		}
	}

	/*
	 * 判断两颗二叉树是否相同
	 */
	public boolean isEquals(TreeNode a, TreeNode b) {
		if (a == null && b == null)
			return true;
		if (a != null && b != null && a.data == b.data
				&& isEquals(a.lChild, b.lChild) && isEquals(a.rChild, b.rChild))
			return true;
		else
			return false;
	}

	// 前序遍历:根左右
	public void preOrder(TreeNode r) {
		if (r != null) {
			System.out.print(r.data + " ");
			preOrder(r.lChild);
			preOrder(r.rChild);
		}

	}

	/*
	 * 中序遍历:左根右
	 */
	public void inOrder(TreeNode r) {
		if (r != null) {
			inOrder(r.lChild);
			System.out.print(r.data + " ");
			inOrder(r.rChild);
		}
	}

	/*
	 * 后序遍历:左右根
	 */
	public void afterOrder(TreeNode r) {
		if (r != null) {
			afterOrder(r.lChild);
			afterOrder(r.rChild);
			System.out.print(r.data + " ");
		}
	}

	// 前序遍历的非递归实现要用到栈
	/*
	 * 实现原理就是:先访问当前根节点,然后判断当前结点的右结点是否为空 不为空压栈,为空在判断左子树是否为空,不为空将当前结点改变为它的左子树结点
	 * 为空弹出栈中和它相邻的右结点。 要点就是要在栈中留下回退的结点,而前序遍历是按照“根左右”的顺序遍历的, 所以回退的结点就是右结点
	 */
	public void preOrderNonRecursion() {
		s = new Stack<TreeNode>();
		TreeNode p = root;
		s.push(null);
		while (p != null) {
			System.out.print(p.data + " ");// 访问根结点
			if (p.rChild != null)
				s.push(p.rChild);// 将右子树结点预留栈中
			if (p.lChild != null)
				p = p.lChild;// 进左子树.
			else
				p = s.pop();
			// System.out.print(s.pop()+" ");
		}
		s = null;
	}

	/*
	 * 中序遍历非递归实现
	 */
	public void inOrderNonRecursion() {
		/*
		 * 一颗二叉子树遍历完毕的标志是它的右孩子为空
		 */
		s = new Stack<TreeNode>();
		TreeNode p = root;
		do {
			// 压入栈中的是左结点以及该左结点的第一个右孩子,
			// 如果这个右孩子还有右孩子,那它将被弹出,将它的右孩子压入栈中.
			while (p != null) {
				s.push(p);
				p = p.lChild;
			}
			if (!s.empty()) {
				p = s.pop();
				System.out.print(p.data + " ");
				p = p.rChild;
			}
		} while (p != null || !s.empty());// 当没有左子树且栈为空【没有右孩子】结束
		s = null;
	}

	/*
	 * 由前序序列和中序序列构造二叉树. x为前序序列, y为中序序列
	 */
	public char[] getChar(char[] m, int start) {
		if (m.length < 1) {
			return null;
		} else {
			if (start >= 1 && start < m.length) {
				int j = start;
				char[] x = new char[m.length - start];
				for (int i = 0; i < x.length; i++) {
					x[i] = m[j++];
				}
				return x;
			}
		}
		return null;
	}

	public TreeNode createBinTree(char[] x, char[] y, int len) {
		if (x != null && y != null) {
			int n;
			if ((n = len) == 0)
				return null;
			int k = 0;
			while (x[0] != y[k])
				k++;// 在中序序列中寻找根节点.
			TreeNode t = new TreeNode(x[0]);// 创建根节点
			t.lChild = createBinTree(getChar(x, 1), y, k);// 构造左子树
			t.rChild = createBinTree(getChar(x, k + 1), getChar(y, k + 1), n
					- k - 1);// 构造右子树
			return t;
		}
		return null;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub

		char[] a = { 'A', 'B', 'H', 'F', 'D', 'E', 'C', 'K', 'G' };
		char[] b = { 'H', 'B', 'D', 'F', 'A', 'E', 'K', 'C', 'G' };
		BinaryTree1 bt = new BinaryTree1(a, b);
		// char[]x=getChar(a,1);
		// for(int i=0;i<x.length;i++){
		// Print.print(" ");
		// }
		Print.print("二叉树节点个数" + bt.size(bt.getRoot()));
		Print.print("二叉树的深度:" + bt.height(bt.getRoot()));
		Print.print("前序遍历:");
		bt.preOrder(bt.getRoot());
		System.out.println();
		Print.print("中序遍历:");
		bt.inOrder(bt.getRoot());
		System.out.println();
		Print.print("后序遍历:");
		bt.afterOrder(bt.getRoot());
		System.out.println();
		Print.print("前序遍历[非递归]:");
		bt.preOrderNonRecursion();
		Print.print("中序遍历非递归\n");
		bt.inOrderNonRecursion();
	}

}

二叉树节点个数9
二叉树的深度:4
前序遍历:
A B H F D E C K G 
中序遍历:
H B D F A E K C G 
后序遍历:
H D F B K G C E A 
前序遍历[非递归]:
A B H F D E C K G 中序遍历非递归


H B D F A E K C G 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值