笔试常考数据结构,所以最近复习了一下数据结构,今天复习到了二叉树,所以写一下笔记。
顺便做了一下测试,参考了网上的一些例子~~~
实现了:二叉树的创建,二叉树的遍历(递归与非递归),求二叉树深度,判断是否为完全二叉树
不说了,直接上代码。
结构大概这样:
最主要的的类:
package binaryTreeTest;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
/**
* @author 5354xyz
* @version 2014-5-4 下午5:27:10
* @E5354xyz-mail: xiaoyizong@126.com
*/
public class BinaryTree {
public String nodevalue;
public BinaryTree leftchild, rightchild;
private Visit onVisitListener ;
public BinaryTree()
{ }
public BinaryTree(String value)
{
nodevalue = value;
}
public void setVisitListener(Visit onVisitListener)
{
this.onVisitListener = onVisitListener;
}
public void assignchild(BinaryTree left, BinaryTree right)//设定左右孩子
{
this.leftchild = left;
this.rightchild = right;
}
public boolean hasleftchild()//是否有左孩子
{
return (this.leftchild != null);
}
public boolean hasrightchild()//是否有右孩子
{
return (this.rightchild != null);
}
public boolean haschild()//是否有孩子
{
return hasleftchild() || hasrightchild();
}
/**
* 计算深度
* 2014-5-4
*
* @author:5354xyz
*/
public int maxDepth(BinaryTree root)
{
if (root == null)
{
return 0;
}
else
{
int leftdepth = maxDepth(root.leftchild);//递归计算左孩子的深度
int rightdepth = maxDepth(root.rightchild);//递归计算右孩子的深度
if (leftdepth >= rightdepth)
{
return leftdepth + 1;
}
else
{
return rightdepth + 1;
}
}
}
/**
* 计算节点数
* 2014-5-4
*
* @author:5354xyz
*/
public int count(BinaryTree subTree){
if(subTree==null){
return 0;
}else{
return 1+count(subTree.leftchild)
+count(subTree.rightchild);
}
}
/**
* 求二叉树第K层的节点个数
* 2014-5-4
*
* @author:5354xyz
*/
int GetNodeNumKthLevel(BinaryTree pRoot, int k)
{
if(pRoot == null || k < 1)
return 0;
if(k == 1)
return 1;
int numLeft = GetNodeNumKthLevel(pRoot.leftchild, k-1); // 左子树中k-1层的节点个数
int numRight = GetNodeNumKthLevel(pRoot.rightchild, k-1); // 右子树中k-1层的节点个数
return (numLeft + numRight);
}
/**
* 前序遍历
* 2014-5-4
*
* @author:5354xyz
*/
public void preOrder(BinaryTree subTree){
if(subTree!=null){
onVisitListener.visit(subTree);
preOrder(subTree.leftchild);
preOrder(subTree.rightchild);
}
}
/**
* 中序遍历
* 2014-5-4
*
* @author:5354xyz
*/
public void inOrder(BinaryTree subTree){
if(subTree!=null){
inOrder(subTree.leftchild);
onVisitListener.visit(subTree);
inOrder(subTree.rightchild);
}
}
/**
* 后续遍历
* 2014-5-4
*
* @author:5354xyz
*/
public void postOrder(BinaryTree subTree) {
if (subTree != null) {
postOrder(subTree.leftchild);
postOrder(subTree.rightchild);
onVisitListener.visit(subTree);
}
}
/**
* 前序遍历的非递归实现
* 2014-5-4
*
* @author:5354xyz
*/
public void nonRecPreOrder(BinaryTree p){
Stack<BinaryTree> stack=new Stack<BinaryTree>();
if (p != null) {
stack.push(p);
while (!stack.empty()) {
p = stack.pop();
onVisitListener.visit(p);
if (p.rightchild != null) //先push,在栈底,实现了根左右
stack.push(p.rightchild);
if (p.leftchild != null)
stack.push(p.leftchild);
}
}
}
/**
* 非递归实现前序遍历2 */
public void nonRecPreOrder2(BinaryTree p){
Stack<BinaryTree> stack=new Stack<BinaryTree>();
BinaryTree node = p;
while (node != null || stack.size() > 0) {
while (node != null) {//压入所有的左节点,压入前访问它
onVisitListener.visit(node);
stack.push(node);
node = node.leftchild;
}
if (stack.size() > 0) {//
node = stack.pop();
node = node.rightchild;
}
}
}
/**
* 中序遍历的非递归实现
* 2014-5-4
*
* @author:5354xyz
*/
public void nonRecInOrder(BinaryTree p){
Stack<BinaryTree> stack =new Stack<BinaryTree>();
BinaryTree node =p;
while(node!=null||stack.size()>0){
//存在左子树
while(node!=null){
stack.push(node);
node=node.leftchild;
}
//栈非空
if(stack.size()>0){
node=stack.pop();
onVisitListener.visit(node);
node=node.rightchild;
}
}
}
//后序遍历的非递归实现
public void noRecPostOrder(BinaryTree p){
Stack<BinaryTree> stack=new Stack<BinaryTree>();
BinaryTree node =p;
while(p!=null){
//左子树入栈
for(;p.leftchild!=null;p=p.leftchild){
stack.push(p);
}
//当前结点无右子树或右子树已经输出
while(p!=null&&(p.rightchild==null||p.rightchild==node)){
onVisitListener.visit(p);
//纪录上一个已输出结点
node =p;
if(stack.empty())
return;
p=stack.pop();
}
//处理右子树
stack.push(p);
p=p.rightchild;
}
}
/**
* 按层遍历二叉树
* 2014-5-4
*
* @author:5354xyz
*/
public void levelTraverse(BinaryTree bTree)
{
if(bTree == null )
return;
Queue<BinaryTree> queue = new LinkedList<BinaryTree>();
queue.offer(bTree);
while(!queue.isEmpty())
{
BinaryTree pNode = queue.poll();
onVisitListener.visit(pNode); // 访问节点
if(pNode.leftchild != null)
queue.offer(pNode.leftchild);
if(pNode.rightchild != null)
queue.offer(pNode.rightchild);
}
return;
}
/**
* 判断二叉树是否为完全二叉树
* 2014-5-4
*
* @author:5354xyz
*/
boolean IsCompleteBinaryTree(BinaryTree pRoot)
{
if(pRoot == null)
return false;
Queue<BinaryTree> q = new LinkedList<BinaryTree>();;
q.offer(pRoot);
boolean mustHaveNoChild = false;
boolean result = true;
while(!q.isEmpty())
{
BinaryTree pNode = q.poll();
if(mustHaveNoChild) // 已经出现了有空子树的节点了,后面出现的必须为叶节点(左右子树都为空)
{
if(pNode.leftchild != null || pNode.rightchild != null)
{
result = false;
break;
}
}
else
{
if(pNode.leftchild != null && pNode.rightchild != null)
{
q.offer(pNode.leftchild);
q.offer(pNode.rightchild);
}
else if(pNode.leftchild != null && pNode.rightchild == null)
{
mustHaveNoChild = true;
q.offer(pNode.leftchild);
}
else if(pNode.leftchild == null && pNode.rightchild != null)
{
result = false;
break;
}
else
{
mustHaveNoChild = true;
}
}
}
return result;
}
}
测试程序:
package binaryTreeTest;
/**
* @author 5354xyz
* @version 2014-5-4 下午5:26:20
* @E5354xyz-mail: xiaoyizong@126.com
*/
public class BinaryTreeTest implements Visit
{
/**
* 2014-5-4
*
* @author:5354xyz
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
BinaryTree node_a = new BinaryTree("a");
BinaryTree node_b = new BinaryTree("b");
BinaryTree node_c = new BinaryTree("c");
BinaryTree node_d = new BinaryTree("d");
BinaryTree node_e = new BinaryTree("e");
BinaryTree node_f = new BinaryTree("f");
BinaryTree node_g = new BinaryTree("g");
BinaryTree node_h = new BinaryTree("h");
BinaryTree node_i = new BinaryTree("i");
BinaryTree node_j = new BinaryTree("j");
//构造一棵二叉树
node_a.assignchild(node_b, node_c);
node_b.assignchild(node_d, node_e);
node_c.assignchild(node_f, node_g);
node_e.assignchild(node_h, node_i);
node_h.assignchild(node_j, null);
/* A
* B C
* D E F G
* H I
* j
*
*/
BinaryTreeTest binaryTreeTest =new BinaryTreeTest();
node_a.setVisitListener(binaryTreeTest);
//输出树的深度
System.out.println("二叉树的深度:"+node_a.maxDepth(node_a));
System.out.println("二叉树的总结点数:"+node_a.count(node_a));
int ceng=4;
System.out.println("二叉树的第"+ceng+"层结点数:"+node_a.GetNodeNumKthLevel(node_a,ceng));
//这个跟
System.out.println("是否是完全二叉树呢?"+node_a.IsCompleteBinaryTree(node_a));
//先序遍历
node_a.preOrder(node_a);
System.out.print(" 递归|非递归 ");
node_a.nonRecPreOrder(node_a);
System.out.print(" 非递归 2 ");
node_a.nonRecPreOrder2(node_a);
System.out.println("先序遍历");
//中序遍历
node_a.inOrder(node_a);
System.out.print(" 递归|非递归 ");
node_a.nonRecInOrder(node_a);
System.out.println("中序遍历");
//后序遍历
node_a.postOrder(node_a);
System.out.print(" 递归|非递归 ");
node_a.noRecPostOrder(node_a);
System.out.println("后序遍历");
//按层遍历
node_a.levelTraverse(node_a);
System.out.println("按层遍历");
}
@Override
public void visit(BinaryTree binaryTreeNode) {
// TODO Auto-generated method stub
System.out.print(binaryTreeNode.nodevalue+" ");
}
}
最后还有个访问的接口:
package binaryTreeTest;
/**
* @author 5354xyz
* @version 2014-5-4 下午5:37:21
* @E5354xyz-mail: xiaoyizong@126.com
*/
public interface Visit {
/**
* visit接口
*/
public void visit(BinaryTree binaryTreeNode);
}
测试的效果: