java遍历完全二叉树

java创建二叉树并且遍历二叉树的几种方式,按层,递归,非递归,分别借助了工具队列和栈

(一).二叉树的重要概念

1.二叉树的定义

二叉树是另一种树形结构,他的特点是每个节点至多有两棵子树(所有节点度都不大于2)并且二叉树有左右之分,其次序不能任意颠倒。

2: 二叉树的类型
 二叉树中两个中比较重要的概念     

    (1) 满二叉树:一个深度为k且有2k-1个节点的二叉树成为满二叉树
    (2)完全二叉树:深度为k有n个节点的二叉树,当且仅当其每一个节点都与深度为k的满二叉树的编号从1至n一一对应时,成为完全二叉树。                 

3: 二叉树的性质(c语言版的数据结构)二叉树中的5个特性

 (1)二叉树的第i层至多有2的(i-1)次方个节点,下图中第三层最多有DEFG四个节点(归纳假设即可证明,过程简单不做赘述,归纳证明的步骤附上,帮自己回忆回忆,哈...)

    1)当n=1时,显然成立.
    2)假设当n=k时(把式中n换成k,写出来)成立,
       则当n=k+1时,(这步比较困难,化简步骤往往繁琐,考试时可以直接写结果)该式也成立.
       由(1)(2)得,原命题对任意正整数均成立

(2)深度为k的二叉树至多有2的k次方减1个节点,下图深度为3,至多有2的3次方减个节点(7个)
    证明过程根据性质(1),前n项求和(首项为1公比为2的前n项求和a1*(1-q∧n)/(1-q))

(3)对于任意一颗二叉树T,如果其终端节点数为n0,度为2的节点数为n2,则n0=n2+1;(终端节点=叶   子节点=度
   为0的节点数)总节点数:n ,终端节点数 n0,度为2的节点数n2,假设度为1的节点数为n1,二叉树中的分支
   (下图中的箭头个数)个数为branch;
    证明
    已知:n=n0+n1+n2①
    因为:出root(A)节点外,其余节点均由一个分支进入故,n=branch+1②
    又因为:所有分支均有由度为1或度为2的节点发出故,branch=n1+2n2③
    由②③得 n=n1+2n2+1④
    由①④得n0=n2+1;

(4) 具有n个节点的二叉树深度为log以2为底的n,向下取整然后减1;
    证明:由前面的性质可得2^(k-1) <= n < (2^k)
        因为三个数均为正数 ,同取log以2为底的对数 k-1 <= log以2为底的n < k  ,因为k是正数,且关 
        系为小于等于 所以log以2为底的n 向下取整;
(5)对于一颗节点为n的完全二叉树,对于任意节点i(1<=1<=n)有(i为元素的顺序下标)
    <1>如果i=1,则节点i是二叉树的根,无双亲;如果 i>1 则其双亲节点是(i/2)向下取整
    <2>如果2*i > n,则节点i无左孩子,要么其左孩子是节点2i
    <3>如果2i+1 > n,则节点i无右孩子,否则其右孩子是节点(2*i+1)

这里写图片描述

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Stack;

public class BinaryTree {
     //定义一个数组
    static char [] letter={'a','b','c','d','e','f','g','h'};
     //定义一个集合将二叉树的元素存起来
    static List <Node> nodeList = null;
    //定义一个内部类
    private static class Node{
        char data; //当前节点的值
        Node leftChild; //当前节点的左孩子的指向
        Node rightChild;//当前节点右孩子的指向
        //内部类的构造方法
        Node(char newData){
            data = newData; //初始化各结点的数值部分
            leftChild = null;
            rightChild = null;
    }
}

/**
 * 创建一棵二叉树
 * 一个有n个节点的二叉树,其非叶子节点既父节点的个数为(n/2)向下取整个
 */
public static void creatBinTree(){
    nodeList = new ArrayList<Node>();
    //用数组的每一个值创建一个Node对象并把并添加到集合中
    for (int arryPointer = 0; arryPointer < letter.length; arryPointer++) {
        nodeList.add(new Node(letter[arryPointer]));
    }
    /**初始化每个根节点对应的左孩子和右孩子
     */
    for (int fatherNode = 0; fatherNode < letter.length/2-1; fatherNode++) {
        nodeList.get(fatherNode).leftChild = nodeList.get(2*fatherNode+1);
        nodeList.get(fatherNode).rightChild = nodeList.get(2*fatherNode+2);
    }
    //单独处理最后一个根节点
    int lastFatherNode =  letter.length/2-1;
    Node lastNode = nodeList.get(lastFatherNode);
    lastNode.leftChild = nodeList.get(2*lastFatherNode+1);
    /**判断确定最后一个节点是否有右孩子
     * 如果n是奇数则最后一个节点有右孩子,如果n为偶数,最后一个节点没有右孩子
     */
    int Remainder = (letter.length % 2);
    if(Remainder == 1){//当数组的长度为奇数时,说明最后这个节点有右孩子
        lastNode.leftChild = nodeList.get(2*lastFatherNode+2);  
    }
}


/** 
 * 后序遍历,采用递归实现
 * 前序和中序遍历与后序类似,未做赘述
 * @param node 根节点
 */
public static void lastOrderPreview(Node node){
    if(node==null){
        return;
    }
    lastOrderPreview(node.leftChild);
    lastOrderPreview(node.rightChild);
    System.out.print(node.data+"  ");
}
/**
 * 
 * @param args
 * 测试
 */
public static void main(String[] args) {
    creatBinTree();//构建一颗二叉树
    Node root = nodeList.get(0); //拿到二叉树的根节点
    byLayerOrder2(root); //按层遍历
     lastOrderPreview(root);//后序遍历
}
/**
 * 按层遍历二叉树
 * 
 */
public static void byLayerOrder2(Node root){
    Node last = root; //每行最后一个结点
    Node nLast = root; 
    Node tempNode;
    Queue<Node> queue = new LinkedList<Node>();//先进后出
    queue.add(nodeList.get(0));
    while (!queue.isEmpty()) {
        tempNode = queue.poll();
        if (tempNode == null) 
            continue;
        System.out.print(tempNode.data+"  ");

        if(tempNode.leftChild != null){
            queue.add(tempNode.leftChild);
            nLast = tempNode.leftChild;
        }
        if(tempNode.rightChild != null){
            queue.add(tempNode.rightChild);
            nLast = tempNode.rightChild;
        }
        if(last == tempNode){
            //输出换行
            System.out.println();
            last = nLast;
        }
    }
}

/**
 * 非递归实现的二叉树遍历  
 * 前序遍历
 * @param
 */
 public static void preOrder2(Node node) { 
        Stack<Node> s = new Stack<Node>(); //先进后出
        while (node != null || !s.empty()) { 
    //输出节点及右孩子的值并压入栈中
            while (node != null) { 
                System.out.print(node.data+" ");    
                s.push(node);    
                node = node.leftChild;    
            }   
            //改变node的值,使node指向节点的左孩子
            if (!s.empty()) {    
                node = s.pop();    
                node = node.rightChild;    
            }    
        }    
    }

}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值