筆試常考數據結構,所以最近複習了一下數據結構,今天覆習到了二叉樹,所以寫一下筆記。
順便做了一下測試,參考了網上的一些例子~~~
實現了:二叉樹的創建,二叉樹的遍歷(遞歸與非遞歸),求二叉樹深度,判斷是否爲完全二叉樹
不說了,直接上代碼。
結構大概這樣:
最主要的的類:
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: [email protected]
*/
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: [email protected]
*/
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: [email protected]
*/
public interface Visit {
/**
* visit接口
*/
public void visit(BinaryTree binaryTreeNode);
}
測試的效果: